将文件从 Vue 发送到 SpringBoot 控制器时清空 MultipartFile[]
Empty MultipartFile[] when sending files from Vue to SpringBoot controller
我正在做一个可以帮助我制作月度报告的程序,但我坚持上传其中一种报告所需的照片。由于某种原因,它没有在控制器中获得数组。
我在后端使用 Springboot RestController,在另一端使用 BootstrapVue 和 vue-resource。
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 库)。
如果你使用 axios 那么你应该添加 header
var headers = {
'Content-Type': 'multipart/form-data',
};
axios.post(
'reports/photo',
formData,
{
headers: headers,
}
)
...
能够将文件发送到服务器。
我在这里找到了一个可接受的解决方案 Rossi Robinsion 的代码运行良好。至少它看起来比在单独的请求中一个一个地发送文件要好。
答案基于使用 getFileNames()
,这有助于在请求中迭代文件,即使它们不在数组中也是如此。
我同意,在单独的请求中一个一个地发送文件非常"ugly",但我也不喜欢不使用 Spring 引导的映射资源的想法,不得不发送所有具有不同名称的文件(似乎杂乱无章)并且必须使用 MultipartHttpServletRequest,但有一个简单的解决方案:伊恩对 this 问题的回答(与 Vue.js 没有真正相关,但很有用)适用于我:
In order for Spring to map items in a request to a list, you need to provide the same name (in the FormData.append calls) for each item when appending to the form data. This allows Spring to effectively see the request as name=value1&name=value2&name=value3 (but obviously in the form of form data). When Spring sees the same key ("name") multiple times, it can map the values into a collection.
在您的 .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
header。确保它在您的请求 header 列表中。
我正在做一个可以帮助我制作月度报告的程序,但我坚持上传其中一种报告所需的照片。由于某种原因,它没有在控制器中获得数组。 我在后端使用 Springboot RestController,在另一端使用 BootstrapVue 和 vue-resource。
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 库)。
如果你使用 axios 那么你应该添加 header
var headers = {
'Content-Type': 'multipart/form-data',
};
axios.post(
'reports/photo',
formData,
{
headers: headers,
}
)
...
能够将文件发送到服务器。
我在这里找到了一个可接受的解决方案 Rossi Robinsion 的代码运行良好。至少它看起来比在单独的请求中一个一个地发送文件要好。
答案基于使用 getFileNames()
,这有助于在请求中迭代文件,即使它们不在数组中也是如此。
我同意,在单独的请求中一个一个地发送文件非常"ugly",但我也不喜欢不使用 Spring 引导的映射资源的想法,不得不发送所有具有不同名称的文件(似乎杂乱无章)并且必须使用 MultipartHttpServletRequest,但有一个简单的解决方案:伊恩对 this 问题的回答(与 Vue.js 没有真正相关,但很有用)适用于我:
In order for Spring to map items in a request to a list, you need to provide the same name (in the FormData.append calls) for each item when appending to the form data. This allows Spring to effectively see the request as name=value1&name=value2&name=value3 (but obviously in the form of form data). When Spring sees the same key ("name") multiple times, it can map the values into a collection.
在您的 .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
header。确保它在您的请求 header 列表中。