vue+element+oss實現前端分片上傳和斷點續傳

dear嫑鬧發表於2021-03-29

純前端實現: 切片上傳 斷點續傳斷點續傳需要在切上上傳的基礎上實現

前端之前上傳OSS,無需後端提供介面。先上完整程式碼,直接複製,將new OSS裡的引數修改成自己公司OSS相關資訊後可用,如遇問題,請繼續往下看。

oss官方文件

https://help.aliyun.com/document_detail/111268.html?spm=a2c4g.11186623.6.1111.5a583a07LknRUO

程式碼允許所需環境:vue + element + ali-oss

安裝ali-oss: cnpm install ali-oss

  • 程式碼實現
<template>
  <div class="dashboard-editor-container">
    <el-upload
      class="upload-demo"
      action=""
      ref="upload"
      :file-list="fileList"
      :limit="2"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :auto-upload="false"
      accept=""
    >
      <el-button slot="trigger" size="small" type="primary">選取檔案</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" @click="submitForm">上傳到伺服器</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" @click="resumeUpload">繼續</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" @click="stopUplosd">暫停</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" @click="abortMultipartUpload">清除切片</el-button>
    </el-upload>
    <el-progress :percentage="percentage" :status="uploadStatus"></el-progress>
  </div>
</template>

<script>
  let OSS = require('ali-oss') // 引入ali-oss外掛
  const client = new OSS({
    region: 'oss-cn-shanghai',//根據那你的Bucket地點來填寫
    accessKeyId: 'LTA*********RaXY',//自己賬戶的accessKeyId
    accessKeySecret: 'uu1************GiS',//自己賬戶的accessKeySecret
    bucket: 'a******o',//bucket名字
  });
export default {
  data () {
    return {
      fileList:[],
      file: null,
      tempCheckpoint: null, // 用來快取當前切片內容
      uploadId: '',
      uploadStatus: null, // 進度條上傳狀態
      percentage: 0, // 進度條百分比
      uploadName: '',  //Object所在Bucket的完整路徑
    }
  },
  mounted() {
    // window.addEventListener('online',  this.resumeUpload);
  },
  methods: {
    // 點選上傳至伺服器
    submitForm(file) {
      this.multipartUpload();
    },
    // 取消分片上傳事件
    async abortMultipartUpload() {
      window.removeEventListener('online', this.resumeUpload)
      const name = this.uploadName; // Object所在Bucket的完整路徑。
      const uploadId = this.upload; // 分片上傳uploadId。
      const result = await client.abortMultipartUpload(name, uploadId);
      console.log(result, '=======清除切片====');
    },
    // 暫停分片上傳。
    stopUplosd () {
      window.removeEventListener('online', this.resumeUpload) // 暫停時清除時間監聽
      let result = client.cancel();
      console.log( result, '---------暫停上傳-----------')
    },
    // 切片上傳
    async multipartUpload () {
      if (!this.file) {
        this.$message.error('請選擇檔案')
        return
      }
      this.uploadStatus = null
      // console.log("this.uploadStatus",this.file, this.uploadStatus);

      this.percentage = 0
      try {
        //object-name可以自定義為檔名(例如file.txt)或目錄(例如abc/test/file.txt)的形式,實現將檔案上傳至當前Bucket或Bucket下的指定目錄。
        let result = await client.multipartUpload(this.file.name, this.file, {
          headers: {
            'Content-Disposition': 'inline',
            'Content-Type': this.file.type //注意:根據圖片或者檔案的字尾來設定,我試驗用的‘.png’的圖片,具體為什麼下文解釋
          },
          progress: (p, checkpoint) => {
            this.tempCheckpoint = checkpoint;
            this.upload = checkpoint.uploadId
            this.uploadName = checkpoint.name
            this.percentage = p * 100
            // console.log(p, checkpoint, this.percentage, '---------uploadId-----------')
            // 斷點記錄點。瀏覽器重啟後無法直接繼續上傳,您需要手動觸發上傳操作。
          },
          meta: { year: 2020, people: 'dev' },
          mime: this.file.type
        });
        console.log(result, this.percentage, 'result= 切片上傳完畢=');
      } catch (e) {
        window.addEventListener('online',  this.resumeUpload) // 該監聽放在斷網的異常處理
        // 捕獲超時異常。
        if (e.code === 'ConnectionTimeoutError') { // 請求超時異常處理
          this.uploadStatus = 'exception'
          console.log("TimeoutError");
          // do ConnectionTimeoutError operation
        }
        // console.log(e)
      }
    },
    // 恢復上傳。
    async resumeUpload () {
      window.removeEventListener('online', this.resumeUpload)
      if (!this.tempCheckpoint) {
        this.$message.error('請先上傳')
        return
      }
      this.uploadStatus = null
      try {
        let result = await client.multipartUpload(this.file.name, this.file, {
          headers: {
            'Content-Disposition': 'inline',
            'Content-Type': this.file.type //注意:根據圖片或者檔案的字尾來設定,我試驗用的‘.png’的圖片,具體為什麼下文解釋
          },

          progress: (p, checkpoint) => {
            this.percentage = p * 100
            console.log(p, checkpoint, 'checkpoint----恢復上傳的切片資訊-------')
            this.tempCheckpoint = checkpoint;
          },
          checkpoint: this.tempCheckpoint,
          meta: { year: 2020, people: 'dev' },
          mime: this.file.type
        })
        console.log(result, 'result-=-=-恢復上傳完畢')
      } catch (e) {
        console.log(e, 'e-=-=-');
      }
    },

    // 選擇檔案發生改變
    handleChange(file, fileList) {
      this.fileList = fileList.filter(row => row.uid == file.uid)
      this.file = file.raw
      // 檔案改變時上傳
      // this.submitForm(file)
    },
    handleRemove(file, fileList) {
      this.percentage = 0 //進度條置空
      this.fileList = []
    },
  }
}
</script>

<style scoped>
</style>

如果相關依賴已經安裝完畢,但是上述程式碼操作時仍有報錯,請檢查以下問題

  const client = new OSS({
    region: 'oss-cn-shanghai',//根據那你的Bucket地點來填寫
    accessKeyId: 'LT******XY',//自己賬戶的accessKeyId
    accessKeySecret: 'uu*********GiS',//自己賬戶的accessKeySecret
    bucket: 'a******io',//bucket名字
  });

配置項中資訊可以問後端或者運維,bucket的名字必須是你OSS上存在的且你有許可權訪問的,不然會一直報 Pleasr create a busket first或者一直報跨域

當遇到跨域時,或者遇到報報錯資訊中有etag時,請檢查OSS配置,然後找有OSS伺服器許可權人員進行配置:

window.addEventListener('online', this.resumeUpload)用於監聽網路狀態(斷網狀態和連網狀態),實現斷網後恢復網路自動上傳就必須設定監聽。

window.removeEventListener('online', this.resumeUpload)取消監聽。如果不設定取消監聽,聯網狀態下會一直處於進行上傳,因為一直滿足監聽條件`

headers: {
            'Content-Disposition': 'inline',
            'Content-Type': this.file.type //注意:根據圖片或者檔案的字尾來設定,我取得是檔案的type,具體為什麼下文解釋
          },

'Content-Type': this.file.type`的作用:加了在檔案上傳完畢後,訪問檔案連結時可以直接檢視,否則會直接下載。

檔案上傳完畢後檢視,可以去resule.res.requestUrls中去取,但是注意要去點地址後面的 ?uploadId=******

上述程式碼只是demo,程式碼以實現功能為主,並不嚴謹,請自行完善。如對各位有所幫助,請推薦,謝謝各位!。

以上就是全部內容,如有疑問,敬請留言!如有問題,請指出,謝謝~~

相關文章