Empty List when trying to upload ma

2020-02-19 08:02发布

I have the following controller method for uploading multiple files at once, inspired by this blog post and answers to this question as well:

@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user, 
                   @RequestParam("file") List<MultipartFile> files) {
  // handle files
}

However, the list of the files is always empty although request contains them.

If I add the third MultipartRequest parameter to the method:

public void upload(@PathVariable User user, 
                   @RequestParam("file") List<MultipartFile> files,
                   MultipartRequest request)

I can see it contains my uploaded files correctly:

request contents

What might be the reason of empty List<MultipartFile>?

I'm using ng-file-upload to submit the files, but I don't think it is connected with the issue. Spring 4.2.4.

4条回答
时光不老,我们不散
2楼-- · 2020-02-19 08:21

I think that in the way you sent data from front, it can not bound with java.util.List. If you create a JSON data as request and you annotated your List with @RequestBody like:

@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user, 
                   @RequestBody List<MultipartFile> files) {
  // handle files
}

this should work. Some info here.

查看更多
可以哭但决不认输i
3楼-- · 2020-02-19 08:25

Try to use @ModelAttribute like this:

    @RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
    @PreAuthorize(...) 
    public void upload(@PathVariable User user,@ModelAttribute("uploadFile") FileUpload uploadFile) throws IllegalStateException, IOException {

    List<MultipartFile> files = uploadFile.getFiles();
    ...

And create a class like:

     public class FileUpload {
     private List<MultipartFile> files;
     public List<MultipartFile> getFiles() {
        return files;
     }

    public void setFiles(List<MultipartFile> files) {
       this.files= files;
      }
   }
查看更多
干净又极端
4楼-- · 2020-02-19 08:29

That works for me, sending big 'email' object with multiple file attachments from UI to back-end:

Angular

sendEmailWithAttachments(taskId: string, template: string, email: any, modelConfig: any, files: any[]) {
    let formData = new FormData();
    formData.append('form', new Blob([JSON.stringify(email)], {type: 'application/json'}));
    files.forEach(file  => {
        formData.append('files', file);
    });

    return this.$http({
        method: 'POST',
        data: formData,
        url: this.baseUrl + '/' + taskId + '/email-with-attachment?template=' + template,
        headers: {
            'Content-Type': undefined
        },
        responseType: 'arraybuffer'
    });
}

Java Spring

@RequestMapping(value = "{taskId}/email-with-attachment", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE)
public void sendEmailWithAttachment(
        @PathVariable String taskId,
        @RequestParam String template,
        @RequestParam("form") MultipartFile form,
        @RequestParam("files") List<MultipartFile> files) throws IOException {
    Map<String, String> parameters = new ObjectMapper().readValue(form.getInputStream(), HashMap.class);

    System.out.println("taskId", taskId);
    System.out.println("template", template);
    System.out.println("files", files);
    System.out.println("parameters", parameters);
}
查看更多
等我变得足够好
5楼-- · 2020-02-19 08:35

The problem was that ng-file-upload by default submits array of files using names file[0], file[1] etc. It is configurable with the arrayKey value when using Upload Service. Setting it to empty string forces the files to be sent under the same file key, which is correctly resolved with Spring and the @RequestParam("file") List<MultipartFile> contains all files that has been submitted.

Upload.upload({url: url, data: {file: arrayOfFiles}, arrayKey: ''})
查看更多
登录 后发表回答