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