项目场景:
后端:实现了一个文件上传服务接口,可以接收前端传递过来的MultipartFile文件,并存储到服务器本地中。
前端:获取type
为file
的标签中的文件,使用
axios
http请求库,发送post
请求,将文件发送给后端。
问题描述
在js中发送上传文件请求的常规代码如下:
new
一个FormData
对象,使用append
方法将文件添加到表单中FormData
专门用于js中发送multipart/form-data
格式请求append
方法的key
为表单中的name
属性,即后端需要接收的参数名
async handleUploadFile(event) { const file = event.target.files[0] let formData = new FormData() formData.append('files', file) const res = await service({ url: '/api/files/upload', method: 'POST', headers: { 'Content-Type': 'multipart/form-data' }, data: formData }) console.log(res.data); }
实际运行以上这段代码时,会发现后端报500
错误如下:
Caused by: java.io.IOException:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
大概的意思是说,后端无法识别到传递来的文件中的boundary
,从而无法区分一个文件的内容从报文的哪个地方开始,又从报文的哪个地方结束,最终导致文件上传失败。
原因分析:
分析以上这种情况的原因,是因为我在发送请求时将请求头中Content-Type
属性给写死为multipart/form-data
,浏览器无法自动给我们的报文添加boundary
我尝试将前端请求config
中,headers
配置移除,如下:
async handleUploadFile(event) { const file = event.target.files[0] let formData = new FormData() formData.append('files', file) const res = await service({ url: '/api/files/upload', method: 'POST', data: formData }) console.log(res.data); }
再次发送请求,这次仍然没有请求成功。服务器没有报错了,但是后端获取不到文件数据。继续分析请求报文,发现属性值变为application/x-www-form-urlencoded
,这是发送普通的表单,肯定是无法正确将文件送达的。
解决方案:
在查阅了网上大量的帖子之后得知,axios
在请求发送出去之前会进行一次拦截,自动给我们的请求设置一些参数。上面会出现application/x-www-form-urlencoded
这个参数就是因为axios
设置了post
请求的默认请求头,如果我们没有在config
中指定其它请求头的话,就会使用默认的。
又了解到,发送multipart/form-data
格式的请求时,不需要我们自己指定Content-Type
属性,由浏览器自动帮我们去设置。
那么解决问题的关键就是不让axios
帮我们自动配置
axios
的config
中有一个transformRequest
属性,官方的解释是可以在请求发送之前让我们人为干预。属性值是一个数组,里面可以定义一个函数,接收两个参数,分别是data
和headers
。data
就是我们刚刚定义的FormData
对象,headers
里面则是axios
预定义的请求头。
打印headers
:
将post
属性中的Content-Type
属性删掉即可解决问题。
最终代码如下:
async handleUploadFile(event) { const file = event.target.files[0] let formData = new FormData() formData.append('files', file) const res = await service({ url: '/api/files/upload', method: 'POST', transformRequest: [function(data, headers) { // 去除post请求默认的Content-Type delete headers.post['Content-Type'] return data }], data: formData }) console.log(res.data); }
以上的解决方法是我不断试错之后得出来的,网上关于这个问题的很多帖子都不能解决,气死我了。。。希望这篇帖子能帮助大家避免踩这个坑吧~
到此这篇关于如何使用axios发送post请求上传文件到后端(multipart/form-data)的文章就介绍到这了,更多相关axios发送post请求上传文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!