【问题标题】:Empty MultipartFile[] when sending files from Vue to SpringBoot controller将文件从 Vue 发送到 SpringBoot 控制器时为空 MultipartFile[]
【发布时间】:2020-05-19 00:15:40
【问题描述】:

我正在做一个程序来帮助我制作月度报告,但我一直坚持上传一种报告所需的照片。出于某种原因,它没有在控制器中获取数组。 我在后端使用 Springboot RestController,在另一端使用带有 BootstrapVue 和 vue-resource 的 Vue。

index.html (BootstrapVue):

  <b-form-file
    v-model="photos"
    accept="image/*"
    multiple
    placeholder="..."
  ></b-form-file>

  <b-button @click="uploadPhotos">Upload</b-button>

vuemain.js 内部:

  data: {
    photos: null,
  },
  methods: {
    uploadPhotos(){
    var formData = new FormData();
    formData.append("photos", this.photos);
    this.$http.post('reports/photo', formData).then(result => {
      ...
    })
  }, ...

控制器内部:

@PostMapping("/photo")
public void addPhoto(@RequestParam("photos") MultipartFile[] photo) {
    System.out.println(photo.length); // shows 0
}

我在浏览器的 Params 中看到的内容:

XHRPOSThttp://localhost:8080/reports-maker/reports/photo
[HTTP/1.1 500  326ms]
Request payload 
-----------------------------4469196632041005505545240657
Content-Disposition: form-data; name="photos"
[object File],[object File],[object File],[object File]
-----------------------------4469196632041005505545240657--

因此,由于某种原因,@RequestParam("photos") MultipartFile[] photo 是空数组。但是,如果我将其更改为仅一张这样的照片:@RequestParam("photos") MultipartFile photo 并从 js 发送一张:formData.append("photos", this.photos[0]); 一切正常,照片将上传到服务器。

这是我第一次使用 Vue,老实说我不想深入 JS 学习,所以可能在某个地方存在一些愚蠢的错误。无论如何,我都可以在 JS 方法中使用循环来一一上传,但这太难看了。我希望有更好的方法来做到这一点(当然不需要任何额外的 JS 库)。

【问题讨论】:

  • 您的 API 是否允许发布数组数据类型或只是对象?

标签: rest spring-boot vue.js multipartform-data vue-resource


【解决方案1】:

我同意,在单独的请求中逐个发送文件非常“丑陋”,但我也不喜欢不使用 Spring Boot 的映射资源的想法,必须发送不同名称的所有文件(似乎杂乱无章) 并且必须使用 MultipartHttpServletRequest,但有一个简单的解决方案:Ian 对this 问题的回答(与 Vue.js 无关,但很有用)对我有用:

为了让 Spring 将请求中的项目映射到列表,您需要在附加到表单数据时为每个项目提供相同的名称(在 FormData.append 调用中)。这使得 Spring 可以有效地将请求视为 name=value1&name=value2&name=value3 (但显然是以表单数据的形式)。当 Spring 多次看到同一个键(“名称”)时,它可以将这些值映射到一个集合中。

在您的 .vue 文件中,附加同名的照片:

for (let i = 0; i < this.photos.length; i++) {
    formData.append("photos", this.photos[i]);
}

在你的控制器中:

@PostMapping("/photo")
public void addPhoto(@RequestParam("photos") MultipartFile[] photo) {
    System.out.println(photo.length); // Should be greater than 0 now
}

注意: 我使用 Vue Axios 来使用我的 API 并手动添加了 Content-Type: multipart/form-data 标头。确保它在您的请求标头列表中。

【讨论】:

    【解决方案2】:

    我在这里找到了一个可以接受的解决方案https://stackoverflow.com/a/33921749/11508625Rossi Robinsion 的代码运行良好。至少它看起来比一个一个地在单独的请求中发送文件要好。

    答案基于使用getFileNames(),它有助于迭代请求中的文件,即使它们不在数组中。

    【讨论】:

      【解决方案3】:

      如果你使用 axios 那么你应该添加标题

      var headers = {
          'Content-Type': 'multipart/form-data',
      };
      
      axios.post(
          'reports/photo', 
          formData,
          {
              headers: headers,
          }
      )
      ...
      

      能够将文件发送到服务器。

      【讨论】:

      • 谢谢,但我没有:(
      • @Hexronimo,看起来b-form-file 组件有问题。检查b-form-file 组件是否有内部字符串'multipart/form-data'。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-16
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      • 2020-01-07
      • 1970-01-01
      相关资源
      最近更新 更多