天天看點

「uniapp實戰筆記」使用app原生上傳替代uniapp的uploadfile接口

作者:博讀代碼

uniapp 是近兩年來比較火的号稱開發者編寫的一套代碼,可釋出到 iOS、Android、Web(響應式)以及各種小程式的一個平台,它提供了各種豐富的 API 文檔讓開發者快速地完成各種功能。

但由于 uniapp 是一個新興平台,生态還不夠完整,難免會出現一些 bug。

本期就來分享一下,uniapp 官方上傳檔案 API 的坑以及如何使用原生 app 寫法代替 uniapp 地上傳接口。

uniapp官方上傳檔案接口uni.uploadFile(OBJECT)

将本地資源上傳到開發者伺服器,用戶端發起一個 POST 請求,其中 content-type 為 multipart/form-data。

接口參數:

「uniapp實戰筆記」使用app原生上傳替代uniapp的uploadfile接口

如果你隻需要上傳檔案而不需要監控實時上傳進度,則可以使用 uni.uploadFile 接口即可。

為何需要使用app原生上傳代替 uniapp官網的uploadFile接口

原因有兩點:

1、如果希望監控上傳進度,則需要傳回一個 uploadTask 對象,用這個對象的 onProgressUpdate 方法是進行監聽上傳進度,使用 abort 方法取消上傳任務。

而這個 uploadTask 對象如果定義為頁面全局對象則 onProgressUpdate 方法和 abort 方法有時候會不執行,導緻無法監聽上傳進度和取消任務。

2、onProgressUpdate 監聽的上傳進度與實際進度不相符。僅表現在安卓端,IOS端無這種情況。

具體原因是我上傳一個30多M的檔案,剛開始進度是0,突然一下子嗖的就變成了100,導緻頁面的進度條也是一下子從0變到100,然後就在100 這裡卡住。其實是遠沒有上傳完的,等了好幾秒才顯示完成。

如何使用app原生上傳檔案

對原生接口文檔感興趣的小夥伴可以從這裡進入。(https://www.html5plus.org/doc/zh_cn/uploader.html)

下面直接貼上我的代碼并通過注釋進行代碼講解。

// 發送檔案方法
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 接口還是很不錯的,使用簡單便捷。原生上傳檔案接口雖然比較複雜,但是好在安卓和蘋果都能支援,保證了相容性。

「uniapp實戰筆記」使用app原生上傳替代uniapp的uploadfile接口

下期給大家分享更多實戰中的點滴,敬請期待~

歡迎各位關注、留言,大家的支援就是我的動力!