首頁 > 軟體

解決axios傳送post請求上傳檔案到後端的問題(multipart/form-data)

2022-05-21 13:01:37

專案場景:

後端:實現了一個檔案上傳服務介面,可以接收前端傳遞過來的MultipartFile檔案,並儲存到伺服器本地中。
前端:獲取typefile<font>標籤中的檔案,使用axioshttp請求庫,傳送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幫我們自動設定

axiosconfig中有一個transformRequest屬性,官方的解釋是可以在請求傳送之前讓我們人為干預。屬性值是一個陣列,裡面可以定義一個函數,接收兩個引數,分別是dataheadersdata就是我們剛剛定義的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請求上傳檔案內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com