Проблема с загрузкой MultipartFile из React/Node
У меня есть следующий контроллер JAVA:
@RequestMapping(value = "/data/upload", method = RequestMethod.POST)
public
@ResponseBody
void uploadData(@RequestParam("file") MultipartFile file) throws IOException {
logger.info("Received File for Ingestion");
dataUploadService.processData(file.getInputStream());
}
Код сервера узла:
serviceCall(serviceCallRequestData, request, finalResponse) {
logger.info('Making remote request: ' + JSON.stringify(serviceCallRequestData));
let file = request.files['file']; // file: Object {name: "sample_aspect_review_upload.csv", encoding: "7bit", mimetype: "text/csv", mv: }
let formData = new FormData();
formData.append('file', Buffer.from(file.data));
fetch(serviceCallRequestData.url, {
method: serviceCallRequestData.requestObject.method,
headers: serviceCallRequestData.requestObject.headers,
body: formData
}).then(response => {
if (response.status !== 200) {
logger.error('Error while making http call requestData: ${JSON.stringify(serviceCallRequestData)}');
finalResponse.status(500).send('Internal server error');
return;
}
return response.json();
}).then((json) => {
logger.info('Returning response for aspect-review-file-upload: ${JSON.stringify(json)}');
finalResponse.status(200).send(JSON.stringify(json));
}).catch((e) => {
logger.error('Error while making http call requestData: ${JSON.stringify(serviceCallRequestData)} error: ${JSON.stringify(e)}');
finalResponse.status(500).send('Internal server error');
});
}
Попытка загрузить файл csv, например:
"product_id","review_id","aspect_id","rating","confidence_score","indices"
"pid","rid","aid",1,0.851955,"[{\"s\":0,\"e\":114,\"highlights\":[39,68]}]"
Загрузка происходит легко из POSTMAN. См. Снимок экрана ниже:
Получение ошибки в JAVA: полученное неизвестное исключение org.springframework.web.bind.MissingServletRequestParameterException: Обязательный параметр "файл" параметра MultipartFile отсутствует, когда я не передаю заголовок ContentType из React.
Получение ошибки в JAVA: org.apache.commons.fileupload.FileUploadException: запрос был отклонен, потому что не было обнаружено многострочной границы, когда я передаю заголовок contentType из React как "Content-Type": "multipart/form-data"
Тот же код на стороне сервера узла для контроллера Dropwizard JAVA:
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Response uploadFile(
@FormDataParam("file") InputStream inputStream,
@FormDataParam("file") FormDataContentDisposition fileDetail
) throws IOException {
logger.debug("Request to upload data file-name: {}", fileDetail.getName());
dataUploadService.processData(inputStream);
return Response.ok().build();
}
работает правильно.
Что я делаю неправильно? Пожалуйста помоги
Ответы
Ответ 1
С curl of postman вы можете увидеть следующую команду:
curl -i -X POST -H "Content-Type:multipart/form-data" -F "[email protected]\"/pathto/sample.csv\";type=text/csv;filename=\"sample.csv\"" 'http://localhost:8080/data/upload'
Поэтому я попытался добавить type=text/csv;filename=\"sample.csv\"
в данные формы, чтобы это работало:
let file = request.files['file'];
let formData = new FormData();
formData.append("file", Buffer.from(file.data), {
filename: file.name,
contentType: file.mimetype,
});
fetch(serviceCallRequestData.url, {
method: serviceCallRequestData.requestObject.method,
headers: serviceCallRequestData.requestObject.headers,
body: formData
}).then(response => {
if (response.status !== 200) {}
});
Ответ 2
Немногие предположения:
-
В определении конечной точки REST вы указываете параметр файла для запроса, который используется для извлечения параметров из самого URI, в то время как многостраничная загрузка файла находится внутри тела запроса POST.
Добавить consumes={}
а вместо @RequestParam
вы можете использовать аннотацию @RequestBody
:
@RequestMapping(value = "/data/upload", method = RequestMethod.POST,
consumes = {"multipart/mixed", "multipart/form-data"}
)
void uploadData(@RequestBody MultipartFile file) //body will be the whole JSON payload
ИЛИ даже лучше использовать @RequestPart
где вы можете назвать элемент:
@RequestMapping(value = "/data/upload", method = RequestMethod.POST,
consumes = {"multipart/mixed", "multipart/form-data"}
)
void uploadData(@RequestPart (value="file") MultipartFile file) //gets file from JSON
-
Предоставьте опции FormData
:
form.append('file', Buffer.from(file.data), {
filename: 'image1.jpg', // ... OR:
filepath: 'photos/image1.jpg',
contentType: 'image/jpeg',
knownLength: 19803
});
form.submit('http://example.com/', function(err, res) {
if (err) throw err;
console.log('Done');
});
Можете ли вы подтвердить (используя что-то вроде WireShark) то, что точно отправлено из React?