I am sending multiple files with formData
like this
In my Spring MVC Controller
@PostMapping(value = "/marches")
public Integer saveMarches(
@RequestPart("formJson") FooBean formJson,
@RequestPart("attachOs") MultipartFile[][] attachOs
) throws IOException {
...
}
My conf :
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(30000000);
return multipartResolver;
}
But i got a 400 Bad Request
in the browser
And in the IDE I got :
Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'attachOs' is not present]
and if i try @RequestPart("attachOs[][]") MultipartFile[][] attachOs
i got always a bad request with Required request part 'attachOs[][]' is not present
The problem is obvious : spring is searching just for attachOs
part (@RequestPart("attachOs")
) but i am sending attachOs[0][0]
, attachOs[0][1]
...
When i send just the formJson
part without files or if i send just a single file @RequestPart("attachOs") MultipartFile attachOs
or one dimension array of files @RequestPart("attachOs") MultipartFile[] attachOs
everything works fine.
Javascript code :
const formData = new FormData();
for (const [i, os] of formJson.os.entries()) {
if(os.attachment) {
for (const [j, file] of [...os.attachment].entries()) {
formData.append(`attachOs[${i}][${j}]`, file );
}
}
}
...
formData.append('formJson',
new Blob([JSON.stringify(formJson)], {type:'application/json'}));
...
axios({
url: ...,
method: 'POST',
data: formData,
})
...
My formJson
structure is
{
// form fields
...
os: [
{
// os form fields
...
attachment: [{ /* File type */ }, ...], // multiple files per os
},
...
]
}
I know that files cannot be sent along with JSON that's why i am constructing the formData above and after that i will delete the attachment property from JSON structure
So my questions :
1. How to fix the bad request issue ?
2. is there another approach or design pattern to handle this use case ?
If you want to send multiple file attachments per OS you can use a List
instead of a 2-dimensional array in the spring controller.
@PostMapping(value = "/marches")
public Integer saveMarches(
@RequestPart("formJson") FooBean formJson,
@RequestPart("attachOs") List<MultipartFile> files
) throws IOException {
// Associate files with their os using the index in their name.
}
and in your angular code append the os index in the name of the file.
for (const [i, os] of formJson.os.entries()) {
if (os.attachment) {
for (const [j, file] of [...os.attachment].entries()) {
formData.append(`attachOs`, file, file.name + ":" + i );
}
}
}
I found a solution by utilizing a @ModelAttribute
(from here);
First create a model class like;
public class MyRequest {
private FooBean formJson;
private MultipartFile[][] attachOs = new MultipartFile[2][2];
// getters/setters
}
Then add it to your controller like;
@PostMapping(value = "/marches", consumes = "multipart/form-data")
public Integer saveMarches(@ModelAttribute MyRequest request) throws IOException {
// some code
}
The important part was the initialization of the MultipartFile[][] attachOs
, otherwise it does not work with multidimensional arrays due to some internal initialization issue.
Or you can use the following type in the model class;
private List<MultipartFile>[] attachOs;
which works without an initialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With