uniapp簡介
uniapp是近兩年來比較火的號稱開發者編寫一套代碼,可發布到iOS、Android、Web(響應式)、以及各種小程序的一個平台,它提供了各種豐富的API文檔讓開發者快速的完成各種功能。
但是由於uniapp是一個新興平台,生態還不夠完整,難免會出現一些bug。今天我們就來講講uniapp官方上傳文件API的坑以及如何使用原生app寫法代替uniapp的上傳接口。
uniapp官方上傳文件接口uni.uploadFile(OBJECT)
將本地資源上傳到開發者服務器,客戶端發起一個 POST 請求,其中 content-type 為 multipart/form-data。
接口參數:

如果你只需要上傳文件而不需要監控實時上傳進度,則使用uni.uploadFile接口即可。
為何需要使用app原生上傳代替 uniapp官網的uploadFile接口
原因有兩點:
1、如果希望監控上傳進度,則需要返回一個 uploadTask 對象,用這個對象的 onProgressUpdate方法進行監聽上傳進度,使用abort方法取消上傳任務。而這個uploadTask對象如果定義為頁面全局對象則onProgressUpdate方法和abort方法有時候會不執行,導致無法監聽上傳進度和取消任務。
2、onProgressUpdate監聽的上傳進度與實際進度不相符。僅表現在安卓端,IOS端無這種情況。具體原因是我上傳一個30多M的文件,剛開始進度是0,突然一下子嗖的就變成了100,導致頁面的進度條也是一下子從0變到100,然后就在100 這里卡住。其實是遠沒有上傳完的。等了好幾秒才顯示完成。
如何使用app原生上傳文件
對原生接口文檔感興趣的小伙伴可以從這里進去。下面我直接貼上我的代碼並通過注釋進行代碼講解。
// 發送文件方法
sendFile(e) {
//filePath是文件的本地路徑,調用plus.io.convertAbsoluteFileSystem方法可以將平台絕對路徑轉換成本地URL路徑
const filePath = plus.io.convertAbsoluteFileSystem(e.filePath)
// 這是后端服務器的文件上傳地址
const url = this.$urlConfig.mattermost + '/plugins/plugin_ruixin_base/file/post'
// 這是創建上傳任務時所需要到的配置參數
const uploadOptions = {
// 分塊上傳的大小單位kb,Android平台需設置分塊上傳才能准確觸發statechanged返回上傳進度,ios自動忽略
chunkSize: 100,
method: 'POST'
}
// 創建上傳任務
this.uploadTask = plus.uploader.createUpload(url,uploadOptions)
// 往上傳任務里添加文件,第二個參數的字段有默認值,可以傳空對象{}即可,但是不能不傳
this.uploadTask.addFile(filePath, {})
// 這里可以將添加文件的返回值打印出來,true表示添加文件成功,false表示添加失敗
// console.log('添加文件', this.uploadTask.addFile(filePath, {}))
// 往接口里添加其他額外的請求參數,第一個參數是key,第二個參數是value
this.uploadTask.addData('string_key1', 'string_value1')
// 這里可以將添加額外請求參數的返回值打印出來,true表示添加成功,false表示添加失敗
// console.log('添加額外請求參數', this.uploadTask.addData('string_key1', 'string_value1'))
this.uploadTask.addData('string_key2', 'string_value2')
// 設置請求頭信息,根據后端接口的要求設置
this.uploadTask.setRequestHeader('headerName1', 'headerValue1')
this.uploadTask.setRequestHeader('headerName2', 'headerValue2')
// 注意:上面addFile、addData中但凡有一個返回false,都不能上傳成功。請檢查是否設置錯了
// 添加事件監聽器用於監聽實時進度和完成情況,第一個參數為“statechanged”,第二個參數是回調方法
this.uploadTask.addEventListener( "statechanged", (upload, status) =>{
switch (upload.state) {
case 1: // 上傳任務開始請求
break
case 2: // 上傳任務請求已經建立
break
case 3: // 上傳任務提交數據,監聽 statechanged 事件時可多次觸發此狀態。(重點)
// uploadedSize表示當前已經上傳了的數據大小,totalSize表示文件總大小,單位是字節b
console.log('上傳進度',parseInt(100 * upload.uploadedSize/upload.totalSize) )
break
case 4: // 上傳任務已完成, 無論成功或失敗都會執行到 4 這里
if (status === 200) {
// 上傳成功
} else {
// 上傳失敗
}
}
})
// 開始執行上傳任務
this.uploadTask.start()
}
運行代碼之后打印出比較精確的實時上傳進度
總結
uniapp上傳文件的接口uploadfile主要的坑在於如果你想監控實時上傳進度,在安卓端它無法提供一個實時准確的上傳進度。如果不需要監控實時上傳進度,使用uploadfile接口還是很不錯的,使用簡單便捷。原生上傳文件接口雖然比較復雜,但是好在安卓和蘋果都能支持,保證了兼容性。
