Element文件上传
图
对于前端的开发中,文件的上传是必不可少的,无论图片、视频、文档的上传,在开发过程中总会遇到,甚至还需要在上传的时候展示实时进度等情况,都是前端开发中需要解决的,文章记录使用element上传组件的使用

上传实时进度

HTML

<el-upload
    :action="uploadUrl"
    :show-file-list="false"
    :on-error="uploadVideoError"
    :on-progress="uploadVideRunning"
    :before-upload="beforeFileUpload"
    :on-success="successFileUpload">
  <el-button size="small" type="primary">点击上传</el-button>
</el-upload>

<!--文件上传进度-->
<div class="upload-progress" v-show="uploadProgressFlag">
  <el-progress :percentage="uploadProgressNum"></el-progress>
</div>

JS

// 上传进度
uploadProgressFlag: false,
uploadProgressNum: 0,

// 文件上传前
beforeFileUpload() {
  this.uploadProgressFlag = true
  this.uploadProgressNum = 0
  //this.load('上传中')
},

// 文件上传计算
uploadVideRunning(event, file, fileList) {
  let uploadProgressNum = (event.loaded / event.total) * 100
  this.uploadProgressNum = parseInt(uploadProgressNum)
  if (this.uploadProgressNum == 100) {
    this.uploadProgressFlag = false
    this.load('等待服务器响应')
  }
},

也可直接使用progress.uploadProgressNum = parseInt(event.percent.toFixed(0))

文件过小无法显示,需要大文件

CSS

/*上传进度*/
.upload-progress {
  width: 100%;
  height: 100vh;
  z-index: 99999999999999;
  position: fixed;
  background-color: rgba(0,0,0,0.3);
  left: 0;
  top: 0;
}
.upload-progress .el-progress {
  width: 300px;
  margin: 48vh auto;
}
.el-progress__text{
  color: #fff !important;
}

上传到阿里OSS

下载阿里OSS的SDK

npm install ali-oss

在页面中导入

import ossItem from 'ali-oss'

利用elemenet提供的http-request覆盖原有的上传逻辑,改为走阿里OSS

<el-upload
    action=""
    :http-request="uploadHttp"
    :before-upload="beforeUploadVideo">
    // 此处添加按钮或图标
</el-upload>

然后处理上传逻辑

// 重写上传方式,走阿里oss
async uploadHttp(file) {
  let _this = this
  // 生产环境此处的信息从接口获取
  let client = ossItem({
    accessKeyId: 'LTAIbOzDzFweJbSR',
    accessKeySecret: '',
    bucket: 'banglin',
    region: 'oss-cn-shenzhen'
  })
  // 文件名处理
  let filename = file.file.name
  let index = filename.lastIndexOf('.')
  let suffix = filename.substr(index)
  let fileUrl = '/servlet/file/' + new Date().getTime().toString() + suffix
  /*
    此方式适用于不显示进度,较为方便,能直接拿到返回的地址
    client.put(new Date().getTime().toString() + suffix, file.file).then(res => {
      console.log(res)
      this.uploadVideoInfo.videoUrl = res.url
      this.uploadProgressFlag = false
      this.close()
    })
  */

  // 此方法能显示上传进度
  let res = await client.multipartUpload(fileUrl, file.file, {
    progress: async function (p) {
      let progress = (p * 100).toFixed(0)
      // 进度值
      _this.uploadProgressNum = parseInt(progress)
    }
  })
  // 显示进度条
  this.uploadProgressFlag = false
  // 处理数据
  if (res.res.status === 200) {
    // 上传成功,拼接URL,res中返回的比较长,也可以用
    this.uploadVideoInfo.videoUrl = 'https://xxxx' + fileUrl
  }
},
// 文件上传之前
beforeUploadVideo() {
  this.uploadProgressFlag = true
  this.uploadProgressNum = 0
},

跨域问题

到阿里控制到对象存储OSS中,找到权限管理 -> 跨域设置

图

以上配置为所有跨域皆支持,也可根据实际情况配置

如果该OSS还开启了CDN,那么还需要配置CDN支持跨域

在存储对象OSS的传输管理 -> 域名管理中可以查看到是否开启了CDN

进入域名配置 -> 缓存配置 -> 自定义HTTP响应头

图

解决跨域问题

Vue通用阿里上传方式

Vue2方式,Vue3同理

// 阿里OSS信息
let OSSClientInfo = {
  accessKeyId: 'xxxx',
  accessKeySecret: 'xxxx',
  bucket: 'xxxx',
  region: 'oss-cn-shenzhen',
  path: '/admin/file/', // 自定义文件上传路径
  url: 'https://oss.aroundme.tv', // OSS配置的访问域名
}

// 阿里OSS文件上传(无进度)
Vue.prototype.ossUpload = async (file) => {
  let client = ossItem({
    accessKeyId: OSSClientInfo.accessKeyId,
    accessKeySecret: OSSClientInfo.accessKeySecret,
    bucket: OSSClientInfo.bucket,
    region: OSSClientInfo.region
  })
  // 文件名处理
  let filename = file.file.name
  let index = filename.lastIndexOf('.')
  let suffix = filename.substr(index)
  let fileUrl = OSSClientInfo.path + new Date().getTime().toString() + suffix
  let url = ''
  await client.put(fileUrl, file.file).then(res => {
    if (res.res.status === 200) {
      // 上传成功,返回地址,更改为自定义域名
      url = OSSClientInfo.url + fileUrl
    } else {
      this.message({code: 1, msg: '文件上传失败'})
    }
  })
  return url
}

使用方式

// element上传组件
<el-upload
    action=""
    :http-request="uploadIcon">
  <img v-if="editData.iconUrl" :src="editData.iconUrl" class="avatar" alt="">
  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>

// 回调
uploadIcon(file) {
  this.ossUpload(file).then(url => {
    this.editData.iconUrl = url
  })
},