尝试使用 ng-file-upload 在 Spring 中上传许多文件时出现空 List<MultipartFile>

Posted

技术标签:

【中文标题】尝试使用 ng-file-upload 在 Spring 中上传许多文件时出现空 List<MultipartFile>【英文标题】:Empty List<MultipartFile> when trying to upload many files in Spring with ng-file-upload 【发布时间】:2016-05-11 16:07:51 【问题描述】:

受this blog post 和this question 的启发,我有以下控制器方法可以一次上传多个文件:

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

但是,尽管请求包含文件,但文件列表始终为空。

如果我在方法中添加第三个MultipartRequest 参数:

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

我可以看到它正确包含我上传的文件:

List&lt;MultipartFile&gt;为空可能是什么原因?

我正在使用ng-file-upload 提交文件,但我认为这与问题无关。春季 4.2.4。

【问题讨论】:

你的配置?您需要一个库和一个匹配的解析器来进行分段上传。 我假设您阅读了您所指的博客文章。 commons-fileupload 例如 是的,我已经完成了所有设置。事实上,我可以通过从multipartRequest.getFileMap().values() 读取这些文件来接收它们。我要问的是为什么我不能像我参考的资料中所建议的那样简单地使用List&lt;MultipartFile&gt; 可能缺少某些东西。例如,如果包含标准 servlet 多部分支持,但您使用 commons 多部分解析器 - 如博客文章中所建议 - 将不会填充 files 是否可以在请求中使用 List 获取 List 【参考方案1】:

尝试像这样使用@ModelAttribute

    @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();
    ...

并创建一个类:

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

    public void setFiles(List<MultipartFile> files) 
       this.files= files;
      
   

【讨论】:

但是我想一次上传多个文件。【参考方案2】:

我认为你从前面发送数据的方式,它不能与java.util.List绑定。如果您创建一个 JSON 数据作为请求并使用 @RequestBody 注释您的列表,例如:

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

这应该可以。一些信息here。

【讨论】:

对我来说不是开箱即用的,但我更喜欢这种方法。最终使用了上面的@francz 方法。 您使用@RequestBody 提出的解决方案实际上在请求正文直接转换为您在后端拥有的域对象时是正确的。例如,它可用于将正文从 JSON 数据解析为对象。但是,它不适用于 MultipartFile。 我能得到 List 和 List 吗? 不使用这种格式的 API 结构,但您可以使用两个列表创建一个 POJO 并尝试使用它。【参考方案3】:

问题是ng-file-upload 默认情况下使用名称file[0]file[1] 等提交文件数组。使用Upload 服务时可以使用arrayKey 值进行配置。将其设置为空字符串会强制使用相同的 file 键发送文件,这可以通过 Spring 正确解析,@RequestParam("file") List&lt;MultipartFile&gt; 包含已提交的所有文件。

Upload.upload(url: url, data: file: arrayOfFiles, arrayKey: '')

【讨论】:

【参考方案4】:

这对我有用,将带有多个文件附件的大“电子邮件”对象从 UI 发送到后端:

角度

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 春天

@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】:

用于多个文件。在您的 javascript 中执行此操作

//first add files to form data
var formData = new FormData();
for (let i = 0; i < files.length; i++) 
    formData.append("images", files[i]);


//post files to backend e.g using angular
 $http.post('upload', formData, 
     transformRequest: angular.identity,
     headers: 'Content-Type': undefined
 )
 .then(function(response)
      console.log("UPLOAD COMPLETE::=> ", response);
 , function (error) 
      console.log(error);
 );

在您的 java 中执行此操作

//your java method signature
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public Response uploadImage(RequestParam(value = "images") MultipartFile[] images)


【讨论】:

以上是关于尝试使用 ng-file-upload 在 Spring 中上传许多文件时出现空 List<MultipartFile>的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会像在 ng-file-upload 示例使用代码中那样在 AngularJS $timeout 服务中包装一个函数,而不会延迟?

当用户在 danialfarid/ng-file-upload 插件中选择不接受的文件时显示警报框

当用户在 danialfarid/ng-file-upload 插件中选择不接受的文件时显示警报框

ngf 前缀在 angularjs 和 ng-file-upload 中是啥意思?

如何使用ng-file-upload裁剪图像和上传?

angularJs中上传图片/文件功能:ng-file-upload