Vue项目使用ant-design-vue文件上传到腾讯云

cos-js-sdk-v5安装使用

首选安装cos-js-sdk-v5

npm install cos-js-sdk-v5

定义BucketRegion

// 桶地址
// config/index.js
export const bucket = {
  Bucket: 'bio-assay-你自己项目的',
  Region: '****你自己项目的****'
}

定义请求方法

我们在项目中封装了http请求的公共方法,同时为看安全起见,将腾讯云的关键信息存储在远程服务器,需要上传文件时,先调用请求获取关键参数。

// 获取上传文件token
const getCosAuth =  function (params) {
    return new Promise((resolve, reject) => {
        Vue.req.get('api/****/****', { options}).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

取消请求

有时候我们需要取消正在上传的文件,则需要一个取消请求的方法

// 请求的集合
export const promiseCancel = {
  cancel: []
}
// 取消请求方法
export const onCancel = (url, message = '') => {
  promiseCancel.cancel.forEach((item) => {
    if (item.url === url) {
      item.cancel && item.cancel(message || item.url)
      promiseCancel.cancel.splice(item, 1)
    }
  })
}

利用MD5生成桶的key

为了保证文件上传的唯一性,我们将根据文件的内容生成唯一的key值

首先需要安装spark-md5

npm install spark-md5
// getFileMD5.js
import SparkMD5 from 'spark-md5'

function getFileMD5 (file, callback) {
  const chunkSize = 1024 * 1024 * 2
  const chunks = Math.ceil(file.size / chunkSize)
  let currentChunk = 0
  const spark = new SparkMD5.ArrayBuffer()
  const fileReader = new FileReader()

  fileReader.onload = (e) => {
    spark.append(e.target.result)
    currentChunk++
    if (currentChunk < chunks) {
      loadNext()
    } else {
      callback(spark.end())
    }
  }

  function loadNext () {
    const start = currentChunk * chunkSize
    const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
    fileReader.readAsArrayBuffer(file.slice(start, end))
  }

  loadNext()
}

export default getFileMD5

完善方法

现在我们来完善一下整体的方法

// upload/index.js
import COS from 'cos-js-sdk-v5'
import getFileMD5 from './getFileMD5'
import { bucket } from './config/index'
import { onCancel } from './http/promiseCancel'
import Vue from 'vue'

export class UploadFile {
  constructor () {
    this.bucketName = bucket.Bucket
    // 监听文件上传的进度,默认是一个空函数
    this.onUploadProgress = () => {}
    // 桶的实例化
    this.cosObj = {}
    // 文件上传的id值
    this.cTaskId = ''
    // 请求token的唯一id值
    this.currentHttpId = ''
    // 取消请求的信息,此处可以忽略
    this.cancelMessage = 'needCancel'
  }

  // 获取上传文件token
  getCosAuth (params) {
    return new Promise((resolve, reject) => {
      Vue.req.get('api/**/**', { params: params, concelkey: this.currentHttpId }).then((res) => {
        resolve(res)
      }).catch((err) => {
        reject(err)
      })
    })
  }

  cancelUpload (msg = 'needCancel') {
    this.cancelMessage = msg
    // 取消获取token
    onCancel(this.currentHttpId, this.cancelMessage)
    // 取消文件上传的请求
    this.cosObj.cancelTask && this.cosObj.cancelTask(this.cTaskId)
  }
  // 文件转成MD5

  fileToMD5 (file, resolve, reject) {
    // 获取文件的md5
    getFileMD5(file, (md5) => {
      const subFix = file.name.substr(file.name.lastIndexOf('.'))
      const key = md5 + subFix
    //   上传到腾讯云
      this.putObject(key, file, resolve, reject)
    })
  }

  // 开始上传文件
  startUpload (file, { progressFn } = {}) {
    // 文件上传的进度监听函数
    this.onUploadProgress = progressFn
    // 生成当前请求的唯一id值
    this.currentHttpId = 'http' + new Date().getTime() + Math.random()
    return new Promise((resolve, reject) => {
      this.getCosAuth({ bucketName: this.bucketName }).then((res) => {
        if (res.actionResult === '1') {
          if (!res.data || !res.data.Credentials) {
            reject(new Error('credentials invalid'))
          } else {
            const _data = res.data.Credentials
            const cosAuth = {
              TmpSecretId: _data.TmpSecretId,
              TmpSecretKey: _data.TmpSecretKey,
              XCosSecurityToken: _data.Token,
              StartTime: res.data.StartTime,
              ExpiredTime: res.data.ExpiredTime,
              ScopeLimit: true
            }
            const AUTH = 'getAuthorization'
            // 保存一下实例
            this.cosObj = new COS({
              [AUTH] (options, callback) {
                callback(cosAuth)
              }
            })
            // 生成md5
            this.fileToMD5(file, resolve, reject)
          }
        } else {
          reject(new Error(res.message))
        }
      }).catch((err) => {
        reject(err)
      })
    })
  }

  // 上传腾讯云
  putObject (key, file, resolve, reject) {
    this.cosObj.putObject({
      Bucket: bucket.Bucket,
      Region: bucket.Region,
      Key: key,
      Body: file,
      onProgress: progressData => {
        // 上传进度条的回调函数
        this.onUploadProgress && this.onUploadProgress(progressData)
      },
      onTaskReady: taskId => {
        this.cTaskId = taskId
      }
    }, (err, data) => {
      if (err) {
        reject(new Error(err.error.Code))
      } else {
        resolve(data)
      }
    })
    // 监听文件上传更新状态
    this.cosObj.on('list-update', (data) => {
      if (data && data.list && data.list[0].state === 'canceled') {
        const errMessage = { message: this.cancelMessage }
        reject(errMessage)
      }
    })
  }
}

以上就是整体的封装方法

组件中使用

现在需要定义一个公共的文件上传组件

改组件依赖了vue的ant-design-vueUI组件库

<template>
  <div>
    <div v-show="isShowUploadBtn" v-if="showUpload" class="upload-warp">
      <a-upload
        name="file"
        ref="upload"
        :multiple="false"
        :disabled="disabled"
        :show-upload-list="false"
        :customRequest="customRequest"
        :accept="accept.join(',')"
        class="upload-list-inline"
        listType="picture">
        <a-button class="upload-btn">
          <my-icon type="iconupload"></my-icon> {{BtnName}}
        </a-button>
      </a-upload>
      <span class="ext-name" v-if="isShowExtNname">支持扩展名:{{ extNname }}</span>
    </div>
    <div v-if="isShowProgress" style="width:90%;" class="progress-warp">
      <p class="t-overflow"><a-icon type="paper-clip" /> {{currentFileName}}</p>
      <div class="progress">
        <a-progress
          :stroke-color="{
            '0%': '#2FC6A3',
            '100%': '#2FC6A3',
          }"
          :percent="percentValue"
        />
        <my-icon type="iconashbin" class="remove" title="点击终止上传" @click="cancelUploadHandler"></my-icon>
      </div>
    </div>
  </div>
</template>
  import { Upload, Icon, Progress } from 'ant-design-vue'
  import { UploadFile } from './index'
  export default {
    name: 'UploadFile',
    components: {
      [Icon.name]: Icon,
      [Progress.name]: Progress,
      [Upload.name]: Upload
    },
    props: {
      accept: {
        type: Array,
        required: false,
        default: () => ['.doc', '.docx']
      },
      disabled: {
        type: Boolean,
        default: false
      },
      files: {
        type: Array,
        default: () => []
      },
      listLenght: {
        type: Number,
        default: 10
      },
      BtnName: {
        type: String,
        default: '上传文件'
      },
      isShowUploadBtn: {
        type: Boolean,
        default: true
      },
      isShowExtNname: {
        type: Boolean,
        default: true
      },
      // 文件上传大小限制
      limtSize: {
        type: Number,
        default: 50
      }
    },
    data () {
      return {
        percentValue: 0,
        currentFileName: '',
        isUploading: false,
        uploadInstance: {}
      }
    },
    computed: {
      showUpload () {
        // 如果是列表上传,则上传文件个数不大最大值,则显示上传按钮
        if (!this.isUploading && this.fileList.length < this.listLenght) {
          return true
        }
        if (!this.fileList.length === 0 && !this.isUploading) {
          return true
        }
        return false
      },
      isShowProgress () {
        return this.isUploading
      }
    },
    methods: {
      // 上传文件 返回腾讯云信息,通过事件将存储信息返回到父组件
      customRequest (info) {
        // console.log(info)
        const { file } = info
        // console.log("handleUpload",file)
        const size = (file.size / 1024 / 1024).toFixed(2)
        this.currentFileName = file.name
        const extName = this.getExtName(file.name)
        const { accept } = this
        this.isUploading = true
        if (accept.length && !accept.includes(`.${extName}`.toLowerCase())) {
          this.$message.error('文件格式错误')
          this.isUploading = false
          return
        }
        if (size > this.limtSize) {
          this.$message.error('上传文件不能大于' + this.limtSize + 'M')
          this.isUploading = false
          return
        }
        this.uploadInstance = new UploadFile()
        this.uploadInstance.startUpload(file, {
          progressFn: this.progress
        }).then(res => {
          if (res.statusCode === 200) {
            this.isUploading = false
            this.percentValue = 0
            this.$emit('fileList', {
              uid: file.uid,
              name: this.currentFileName,
              url: 'https://' + res.Location
            })
          }
        }).catch((err) => {
          this.percentValue = 0
          this.isUploading = false
          if (err && err.message === 'needCancel') {
            this.$message.warning('文件上传已取消!')
          } else {
            this.$message.warning(err.message || err || '上传异常!')
          }
        })
      },
      // 监听文件上传的进度
      progress (data) {
        this.percentValue = data.percent ? +(data.percent * 100).toFixed(2) : 0
      },
      cancelUploadHandler () {
        // 取消文件上传
        this.uploadInstance.cancelUpload && this.uploadInstance.cancelUpload()
      }
    }
}

以上代码仅显示了文件上传的关键逻辑,如果想拓展功能,可以自行添加代码

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Vue3.0中使用ant-design-vue上传文件,需要先安装ant-design-vue和axios模块: ```bash npm install ant-design-vue axios --save ``` 然后在需要使用上传组件的页面中,引入ant-design-vue和axios模块: ```javascript import { Upload, Button } from 'ant-design-vue'; import axios from 'axios'; ``` 然后在页面中,添加上传组件: ```html <template> <div> <upload :action="uploadUrl" :headers="headers" :showUploadList="false" :beforeUpload="beforeUpload" :onSuccess="onSuccess" :onError="onError" > <button> <a-button> <a-icon type="upload" /> Click to Upload </a-button> </button> </upload> </div> </template> ``` 其中,`uploadUrl`是上传文件的接口地址,`headers`是上传文件时需要携带的请求头,`beforeUpload`是上传文件前的校验函数,`onSuccess`和`onError`分别是上传成功和上传失败的回调函数。 在页面的`script`中,需要定义这些属性的值以及`beforeUpload`、`onSuccess`、`onError`函数的实现: ```javascript export default { name: 'UploadPage', components: { Upload, Button }, data() { return { uploadUrl: '/api/upload', headers: { Authorization: 'Bearer ' + localStorage.getItem('token') } }; }, methods: { beforeUpload(file) { const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; if (!isJpgOrPng) { this.$message.error('You can only upload JPG/PNG file!'); return false; } const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { this.$message.error('Image must smaller than 2MB!'); return false; } return true; }, onSuccess(response, file) { this.$message.success('Upload successfully!'); }, onError(error, response, file) { this.$message.error('Upload error!'); } } }; ``` 其中,`beforeUpload`函数用来进行文件类型和大小的校验,`onSuccess`和`onError`函数用来处理上传成功和上传失败的情况。 最后,在页面的`style`中,可以添加一些样式来美化上传按钮: ```css button { margin-top: 16px; } button .ant-btn { width: 100%; } button .anticon-upload { margin-right: 8px; } ``` 这样,就可以在Vue3.0中使用ant-design-vue上传文件了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绝对零度HCL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值