文章目录
- Intro
- 错误原因 & 解决
- 正确的前端请求方式 MDN
Intro
前端使用 form 提交文件到后端。
使用 jquery/axios/fetch 或其他HTTP客户端程序发送HTTP请求,但是后端(Spring框架)报错如下:
Request processing failed;
nested exception is org.springframework.web.multipartException: Failed to parse multipart servlet request;
nested exception is java.io.IOException:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
错误原因 & 解决
我是因为设置了 "Content-Type": "multipart/form-data"
这样的头,才会失败。
这个请求头的格式样例(见https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type):
POST /foo HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575
...
其中 multipart/form-data
表示请求内容的数据类型,而后的 boundary和值表示发送数据的边界(用于确定文件何时结束 EOF)。
那我加上 boundary 参数?
可是 boundary 的值是由上传文件的大小影响的,我怎么去确定啊?
答案是不用确定。
(程序员)不要发送 Content-Type
这个请求头。
ref: https://stackoverflow.com/questions/35192841/how-do-i-post-with-multipart-form-data-using-fetch
make sure not to set the Content-Type header. The browser will set it for you, including the boundary parameter.
一定不要在发送请求的时候自己用javascript去设置 Content-Type 头!
浏览器会替你自动设置这个请求头的值(包括 bounday 参数)!
正确的前端请求方式 MDN
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#uploading_a_file
const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');
formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);
fetch('https://example.com/profile/avatar', {
method: 'PUT',
// headers: {
// "Content-Type": "multipart/form-data" // 我们手动加这个header会导致错误,让浏览器自己去设置这个header即可!
// },
body: formData
})
.then((response) => response.json())
.then((result) => {
console.log('Success:', result);
})
.catch((error) => {
console.error('Error:', error);
});