vue + elementUI (el-upload) + 阿里oss 上传文件(视频,图片等) 并 显示上传进度条

先来看上传效果

vue + elementUI (el-upload) + 阿里oss 上传文件(视频,图片等) 并 显示上传进度条_第1张图片

1.先安装alioss

npm i ali-oss --save

2.安装完事之后,进行引入并进行oss的初始化,这里把初始化和后面用到的UUID生成规则放在一起,ali-oss.js文件

// 引入ali-oss
let OSS = require('ali-oss')
/**
 *  [accessKeyId] {String}:通过阿里云控制台创建的AccessKey。
 *  [accessKeySecret] {String}:通过阿里云控制台创建的AccessSecret。
 *  [bucket] {String}:通过控制台或PutBucket创建的bucket。
 *  [region] {String}:bucket所在的区域, 默认oss-cn-hangzhou。
 */
export function client(data) {//data后端提供数据
  return new OSS({
    region: data.region,
    accessKeyId: data.accessKeyId,
    accessKeySecret:  data.accessKeySecret,
    bucket: data.bucket
  })
}

/**
 * 生成随机文件名称
 * 规则八位随机字符,加下划线连接时间戳
 */
export const getFileNameUUID = () => {
  function rx() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
  }
  return `${+new Date()}_${rx()}${rx()}`
}

3.组件内使用

oss文件上传分为Blob数据上传 和 断点上传也就是分片上传,这里的展示是分片上传功能,关于文件上传官方文档请参阅 上传文件
(1)html部分

<template>
  <div class="content">
    <el-upload
      action
      :http-request="Upload"
      :before-upload="beforeAvatarUpload"
      :on-preview="handlePreview"
      :before-remove="beforeRemove"
      :on-remove="handleRemove"
      :on-success="handleSuccess"
      :on-exceed="handleExceed"
      drag
      :limit="limit"
      :file-list="fileList"
    >
      <i class="el-icon-upload">i>
      <div class="el-upload__text">
        将文件拖到此处,或
        <em>点击上传em>
      div>
      <div slot="tip" class="el-upload__tip">上传文件大小不能超过 1Gdiv>
    el-upload>

    <el-progress
      v-show="showProgress"
      :text-inside="true"
      :stroke-width="15"
      :percentage="progress"
    >el-progress>
  div>
template>

(2)js部分

import { client , getFileNameUUID  } from "@/utils/ali-oss"; //前面的ali-js文件内的两个封装函数
import { getAliOSSConfig } from "@/api/admin";  //请求后台的接口拿Ali-OSS数据
export default {
  name: "Upload",
  props: {
    limit: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      fileList: [],//文件列
      showProgress: false,//进度条的显示
      dataObj: {}, //存签名信息
      progress: 0 //进度条数据
    };
  },
  methods: {
    // 文件超出个数限制时的钩子
    handleExceed(files, fileList) {
      this.$message.warning(`每次只能上传 ${this.limit} 个文件`);
    },
    // 点击文件列表中已上传的文件时的钩子
    handlePreview(file) {},
    // 删除文件之前的钩子
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${file.name}?`);
    },
    // 文件列表移除文件时的钩子
    handleRemove(file, fileList) {},
    // 文件上传成功时的钩子
    handleSuccess(response, file, fileList) {
      this.fileList = fileList;
    },
    //文件上传前的校验
    beforeAvatarUpload(file) {
      const isLt100M =
        file.size / 1024 / 1024 > 10 && file.size / 1024 / 1024 < 1024;
      const isLt30 = file.name.length < 30;
      if (["video/mp4"].indexOf(file.type) == -1) {
        this.$message.error("请上传正确的视频格式");
        return false;
      }
      if (!isLt100M) {
        this.$message.error("上传视频大小要在10MB~1GB之间哦!");
        return false;
      }
      if (!isLt30) {
        this.$message.error("上传视频文件名称长度必须要小于30个文字哦!");
        return false;
      }
	  // 请求后台接口拿配置参数
      return new Promise((resolve, reject) => {
        getAliOSSConfig()
          .then(response => {
            this.dataObj = response.data; //接口返回配置参数
            console.log(response.data);
            resolve(true);
          })
          .catch(err => {
            console.log(err);
            reject(false);
          });
      });
    },
    // http-request属性来覆盖默认的上传行为(即action="url"),自定义上传的实现 
    Upload(file) {
      const that = this;
      async function multipartUpload() {
        let temporary = file.file.name.lastIndexOf(".");
        let fileNameLength = file.file.name.length;
        let fileFormat = file.file.name.substring(
          temporary + 1,
          fileNameLength
        );
        let fileName = getFileNameUUID() + "." + fileFormat; 
        client(that.dataObj)
          .multipartUpload(`videoTest/${fileName}`, file.file, {
            progress: function(p) {
              //p进度条的值
              console.log(p);
              that.showProgress = true;
              that.progress = Math.floor(p * 100);
            }
          })
          .then(result => {
            //上传成功返回值,可针对项目需求写其他逻辑
            console.log(result);
          })
          .catch(err => {
            console.log("err:", err);
          });
      }
      multipartUpload();
    }
  }
};
</script>

(3)至此以上内容就完成了文件分片上传并显示进度条,遇到问题参阅如下:

出现问题
上传出现跨域问题,或者出现分片上传 最后一个请求报错 One or more of the specified parts could not be found or the specified entity tag might not have matched the part’s entity tag 错误
解决办法
在阿里云oss控制台 基础设置 > 跨域规则设置 > 编辑规则 “允许 Headers”添加 ‘ * ’ 即可解决跨域问题, “暴露 Headers” 中增加 ‘ ETag ’ 即可解决分片上传最后一个请求报错报错问题
vue + elementUI (el-upload) + 阿里oss 上传文件(视频,图片等) 并 显示上传进度条_第2张图片

出现问题
怎么设置callback函数,如何在URL中携带参数,关于callback的官方文档
解决办法
在client.multipartUpload参数中,例如:

callback: {
  url: 'http://oss-demo.aliyuncs.com:23450',
  host: 'oss-cn-hangzhou.aliyuncs.com',
  body: 'bucket=${bucket}&object=${object}&var1=${x:var1}',
  contentType: 'application/x-www-form-urlencoded',
  customValue: {
    var1: 'value1',
    var2: 'value2',
  },
},

你可能感兴趣的:(VUE)