我想将表单内的文件上传到 Spring Boot API 端点。
UI 是用 React 编写的:
export function createExpense(formData) {
return dispatch => {
axios.post(ENDPOINT,
formData,
headers: {
'Authorization': //...,
'Content-Type': 'application/json'
}
).then(({data}) => {
//...
})
.catch(({response}) => {
//...
});
};
}
_onSubmit = values => {
let formData = new FormData();
formData.append('title', values.title);
formData.append('description', values.description);
formData.append('amount', values.amount);
formData.append('image', values.image[0]);
this.props.createExpense(formData);
}
这是java端代码:
@RequestMapping(path = "/{groupId}", method = RequestMethod.POST)
public ExpenseSnippetGetDto create(@RequestBody ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal, BindingResult result) throws IOException {
//..
}
但是我在 Java 端遇到了这个异常:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryapHVvBsdZYc6j4Af;charset=UTF-8' not supported
我应该如何解决这个问题?类似的 API 端点和 JavaScript 端代码已经在运行。
注意
我见过一个解决方案,它建议请求正文应该有 2 个属性:一个属性包含 JSON 部分,另一个属性包含图像。我想看看是否可以将其自动转换为 DTO。
<小时/>更新 1
客户端发送的上传负载应转换为以下 DTO:
public class ExpensePostDto extends ExpenseBaseDto {
private MultipartFile image;
private String description;
private List<Long> sharers;
}
所以你可以说它是 JSON 和多部分的混合。
<小时/>解决方案
解决问题的方法是在前端使用FormData
,在后端使用ModelAttribute
:
@RequestMapping(path = "/{groupId}", method = RequestMethod.POST,
consumes = {"multipart/form-data"})
public ExpenseSnippetGetDto create(@ModelAttribute ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal) throws IOException {
//...
}
在前端,摆脱Content-Type
,因为它应该由浏览器本身确定,并使用FormData
(标准JavaScript)。这应该可以解决问题。
最佳答案
是的,您可以简单地通过包装类来完成。
1) 创建一个Class
来保存表单数据:
public class FormWrapper {
private MultipartFile image;
private String title;
private String description;
}
2) 创建一个 HTML form
用于提交数据:
<form method="POST" enctype="multipart/form-data" id="fileUploadForm" action="link">
<input type="text" name="title"/><br/>
<input type="text" name="description"/><br/><br/>
<input type="file" name="image"/><br/><br/>
<input type="submit" value="Submit" id="btnSubmit"/>
</form>
3) 创建一个方法来接收表单的text
数据和multipart
文件:
@PostMapping("/api/upload/multi/model")
public ResponseEntity<?> multiUploadFileModel(@ModelAttribute FormWrapper model) {
try {
// Save as you want as per requiremens
saveUploadedFile(model.getImage());
formRepo.save(mode.getTitle(), model.getDescription());
} catch (IOException e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity("Successfully uploaded!", HttpStatus.OK);
}
4) 保存文件
的方法:
private void saveUploadedFile(MultipartFile file) throws IOException {
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
Files.write(path, bytes);
}
}
关于javascript - Spring Boot Controller - 将 Multipart 和 JSON 上传到 DTO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49845355/