解決axios發(fā)送post請求上傳文件到后端的問題(multipart/form-data)
項目場景:
后端:實現(xiàn)了一個文件上傳服務(wù)接口,可以接收前端傳遞過來的MultipartFile文件,并存儲到服務(wù)器本地中。
前端:獲取type
為file
的<font>
標(biāo)簽中的文件,使用axios
http請求庫,發(fā)送post
請求,將文件發(fā)送給后端。
問題描述
在js中發(fā)送上傳文件請求的常規(guī)代碼如下:
new
一個FormData
對象,使用append
方法將文件添加到表單中FormData
專門用于js中發(fā)送multipart/form-data
格式請求append
方法的key
為表單中的name
屬性,即后端需要接收的參數(shù)名
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); }
實際運行以上這段代碼時,會發(fā)現(xiàn)后端報500
錯誤如下:
Caused by: java.io.IOException:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
大概的意思是說,后端無法識別到傳遞來的文件中的boundary
,從而無法區(qū)分一個文件的內(nèi)容從報文的哪個地方開始,又從報文的哪個地方結(jié)束,最終導(dǎo)致文件上傳失敗。
原因分析:
分析以上這種情況的原因,是因為我在發(fā)送請求時將請求頭中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); }
再次發(fā)送請求,這次仍然沒有請求成功。服務(wù)器沒有報錯了,但是后端獲取不到文件數(shù)據(jù)。繼續(xù)分析請求報文,發(fā)現(xiàn)屬性值變?yōu)?code>application/x-www-form-urlencoded,這是發(fā)送普通的表單,肯定是無法正確將文件送達(dá)的。
解決方案:
在查閱了網(wǎng)上大量的帖子之后得知,axios
在請求發(fā)送出去之前會進(jìn)行一次攔截,自動給我們的請求設(shè)置一些參數(shù)。上面會出現(xiàn)application/x-www-form-urlencoded
這個參數(shù)就是因為axios
設(shè)置了post
請求的默認(rèn)請求頭,如果我們沒有在config
中指定其它請求頭的話,就會使用默認(rèn)的。
又了解到,發(fā)送multipart/form-data
格式的請求時,不需要我們自己指定Content-Type
屬性,由瀏覽器自動幫我們?nèi)ピO(shè)置。
那么解決問題的關(guān)鍵就是不讓axios
幫我們自動配置
axios
的config
中有一個transformRequest
屬性,官方的解釋是可以在請求發(fā)送之前讓我們?nèi)藶楦深A(yù)。屬性值是一個數(shù)組,里面可以定義一個函數(shù),接收兩個參數(shù),分別是data
和headers
。data
就是我們剛剛定義的FormData
對象,headers
里面則是axios
預(yù)定義的請求頭。
打印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請求默認(rèn)的Content-Type delete headers.post['Content-Type'] return data }], data: formData }) console.log(res.data); }
以上的解決方法是我不斷試錯之后得出來的,網(wǎng)上關(guān)于這個問題的很多帖子都不能解決,氣死我了。。。希望這篇帖子能幫助大家避免踩這個坑吧~
到此這篇關(guān)于如何使用axios發(fā)送post請求上傳文件到后端(multipart/form-data)的文章就介紹到這了,更多相關(guān)axios發(fā)送post請求上傳文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Vue做一個簡單的todo應(yīng)用的三種方式的示例代碼
這篇文章主要介紹了使用Vue做一個簡單的todo應(yīng)用的三種方式的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10vue.js動態(tài)設(shè)置VueComponent高度遇到的問題及解決
這篇文章主要介紹了vue.js動態(tài)設(shè)置VueComponent高度遇到的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08使用vue 國際化i18n 實現(xiàn)多實現(xiàn)語言切換功能
這篇文章主要介紹了使用vue 國際化i18n 多實現(xiàn)語言切換功能,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下2018-10-10vue+socket.io+express+mongodb 實現(xiàn)簡易多房間在線群聊示例
本篇文章主要介紹了vue+socket.io+express+mongodb 實現(xiàn)簡易多房間在線群聊示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-10-10vue-router跳轉(zhuǎn)時打開新頁面的兩種方法
這篇文章主要給大家介紹了關(guān)于vue-router跳轉(zhuǎn)時打開新頁面的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue-router具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07從0到1構(gòu)建vueSSR項目之node以及vue-cli3的配置
這篇文章主要介紹了從0到1構(gòu)建vueSSR項目之node以及vue-cli3的配置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03