我想将表单内的文件上传到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。
客户端发送的上载负载应转换为以下DTO:
public class ExpensePostDto extends ExpenseBaseDto { private MultipartFile image; private String description; private List<Long> sharers; }
因此,您可以说这是JSON和 multipart 的混合。
该问题的解决方案是FormData在前端和ModelAttribute后端上使用:
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)。那应该解决问题。
Content-Type
是的,您可以简单地通过包装类来实现。
1)创建一个Class保存表单数据:
Class
public class FormWrapper { private MultipartFile image; private String title; private String description; }
2)创建form用于提交数据的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文件的方法:
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)保存方法file:
file
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); } }