最近在開發過程當中,遇到的須要是須要上傳高清圖片,必須原圖上傳。因爲在移動端應用,上傳網絡問題有很大的坑。當初的方案是直接採用將文件轉化爲base64
,再進行上傳,因爲文件轉化爲base64
後,文件大小會增長30%。又致使上傳壓力,影響用戶體驗。最終採起了以formData
形式進行上傳,也就是 File 上傳文件。以這種形式能夠提升上傳速度提升30%以上。下面會講解開發過程及遇到的問題。ios
經過input標籤,咱們能夠獲得一個file文件將這個file進行處理。json
<input class="upload" type="file" ref="upload" accept="image/jpeg,image/jpg,image/png" @change="uploadImg($event)">
axios
// 選擇本地圖片
uploadImg (e) {
let file = e.target.files[0]
}
複製代碼
由於咱們是以表單的形式上傳文件,因此必須進行實例化,再添加屬性以及值。注意,這裏必須進行實例化,不然沒法上傳。咱們能夠把formdata
做爲參數上傳給後端。後端
uploadImg (e) {
// 獲取file
let file = e.target.files[0]
// 實例化
let formdata = new FormData()
formdata.append('file', file)
}
複製代碼
在axios配置中,咱們須要用POST方法,再配置headers
,須要這個瀏覽器才知道是表單。瀏覽器
headers: {
'Content-Type': 'multipart/form-data;charset=UTF-8'
}
複製代碼
uploadImg (e) {
// 獲取file
let file = e.target.files[0]
// 實例化
let formdata = new FormData()
formdata.append('file', file)
upload(formdata).then(res => {
// ...
})
}
複製代碼
基本的步驟就以上3個,可是開發過程當中會遇到一些不明覺厲的坑,下面總結一下。bash
因爲出現請求參數爲空,咱們沒法發送給後端數據,沒法保存成功。遇到這個能夠檢查一下你的axios請求攔截部分是否對數據進行了處理,我遇到是的axios請求攔截中,multipart/form-data時候,數據直接就被Qs進行序列化了,由於沒法序列化FormData的內容,因此返回的data就是一個空的內容,致使最後判斷是否是formData對象時出錯。解決方法,若是'Content-Type' === 'multipart/form-data;charset=UTF-8'
就是直接返回data,不進行序列化。網絡
transformRequest: [function (data, headers) {
if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
// 把一個參數對象格式化爲一個字符串
return qs.stringify(data)
} else if (headers['Content-Type'] === 'multipart/form-data;charset=UTF-8') {
return data
} else {
headers['Content-Type'] = 'application/json'
}
return JSON.stringify(data)
}]
複製代碼
請求報文中出現了這個boundary
,按道理咱們沒有加上去,那怎麼會增長這個東西呢。其實這個是瀏覽器本身加上去的。若是你們去看axios中源碼,處理請求頭部分,以下:app
axios會自動的判斷是不是以formData
的形式上傳,就將Content-Type刪除,也就是刪除掉了multipart/form-data這個請求頭。由於這種形式須要瀏覽器自行設置才能夠進行上傳。ui
這種方式上傳相對比較簡單,也能夠減小帶寬的壓力,不過須要後端進行配置處理比較多,根據需求進行合理利用。url