Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
92
rated 0 times [  99] [ 7]  / answers: 1 / hits: 154896  / 6 Years ago, sun, april 15, 2018, 12:00:00

I want to upload a file inside a form to a Spring Boot API endpoint.



The UI is written in 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);
}


This is the java side code:



@RequestMapping(path = /{groupId}, method = RequestMethod.POST)
public ExpenseSnippetGetDto create(@RequestBody ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal, BindingResult result) throws IOException {
//..
}


But I get this exception on the Java side:



org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryapHVvBsdZYc6j4Af;charset=UTF-8' not supported


How should I resolve this issue? The similar API endpoints and JavaScript side code is already working.



Note



I've seen a solution where it suggests that the request body should have 2 attributes: one which the JSON section goes under, another for the image. I'd like to see if it is possible to have it automatically converted to DTO.






Update 1



The upload payload sent by the client should be converted to the following DTO:



public class ExpensePostDto extends ExpenseBaseDto {

private MultipartFile image;

private String description;

private List<Long> sharers;

}


So you can say it's a mix of JSON and multipart.






Solution



The solution to the problem is to use FormData on the front-end and ModelAttribute on the backend:



@RequestMapping(path = /{groupId}, method = RequestMethod.POST,
consumes = {multipart/form-data})
public ExpenseSnippetGetDto create(@ModelAttribute ExpensePostDto expenseDto, @PathVariable long groupId, Principal principal) throws IOException {
//...
}


and on the front-end, get rid of Content-Type as it should be determined by the browser itself, and use FormData (standard JavaScript). That should solve the problem.


More From » java

 Answers
9

Yes, you can simply do it via wrapper class.



1) Create a Class to hold form data:



public class FormWrapper {
private MultipartFile image;
private String title;
private String description;
}


2) Create an HTML form for submitting data:



<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) Create a method to receive form's text data and multipart file:



@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) Method to save 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);
}
}

[#54656] Thursday, April 12, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
brodyfrancisi

Total Points: 1
Total Questions: 102
Total Answers: 89

Location: Marshall Islands
Member since Mon, May 31, 2021
3 Years ago
brodyfrancisi questions
;