解決axios發送post請求上傳文件到後端的問題(multipart/form-data)
項目場景:
後端:實現瞭一個文件上傳服務接口,可以接收前端傳遞過來的MultipartFile文件,並存儲到服務器本地中。
前端:獲取type
為file
的<font>
標簽中的文件,使用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請求上傳文件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- vue封裝el-upload批量上傳隻請求一次接口
- 解析element-ui中upload組件傳遞文件及其他參數的問題
- Vue使用axios圖片上傳遇到的問題
- vue+vant 上傳圖片需要註意的地方
- Vue使用formData格式類型上傳文件的示例