element ui 文件上传 + MD5 + axios

文件上传

上传方法:

  • action
  • :http-request="onUpload" 自定义上传方法

上传方式

  • 手动上传
    调用 this.$refs.uploadFile.submit()
  • 自动上传
    :auto-upload=“true”

上传前校验:beforeUpload

返回boolean 与 promise结果
如果false,reject 则停止上传

axios 上传进度

onUploadProgress 钩子 获取进度
设置fileList 中file的status与 percentage 看element 源码
status 状态:ready | uploading | sucess | fail

检验与上传都是单个进行的

中断上传, 取消上传

axios的cancelToken

    <el-upload
      ref="uploadFile"
      action=""
      :on-change="onChange"
      :http-request="onUpload"
      :on-remove="onRemove"
      :before-upload="beforeUpload"
      :file-list="fileList"
      :auto-upload="true"
      :limit="1"
      :on-exceed="handleExceed"
      class="document-upload"
    >
      <el-button :loading="loading" size="small" type="primary" class="mr">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">仅支持文件大小不超过50Mb</div>
    </el-upload>
  </div>
import SparkMD5 from 'spark-md5'
import { upload, CancelToken } from '@/utils/docRequset'
import { validateFileMd5 } from '@/api/file'
data() {
	return {
   		TipText: '当前仅支持不大于50M的文件',
      	typeTip: '文档格式支持:.doc、.docx、.xls 、.xlt、 .xlsx、.xlsm、.ppt、.pptx、.pdf、.pages',
      	MineTypes: ['application/msword',
      	    'application/wps-writer', // doc
	        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
	        'application/x-xls',
	        'application/vnd.ms-excel',
	        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
	        'application/vnd.ms-excel.sheet.macroEnabled.12', // windows
	        'application/vnd.ms-excel.sheet.macroenabled.12', // mac
	        'application/vnd.ms-powerpoint',
	        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
	        'application/pdf',
	        ''],
      	extensions: ['doc', 'docx', 'xls', 'xlt', 'xlsx', 'xlsm', 'ppt', 'pptx', 'pdf', 'pages']
	}
}
async getFileMd5(file) {
      const blobSlice = window.File.prototype.slice || window.File.prototype.mozSlice || window.File.prototype.webkitSlice
      const chunkSize = 2097152 // Read in chunks of 2MB
      const chunks = Math.ceil(file.size / chunkSize)
      let currentChunk = 0
      const spark = new SparkMD5.ArrayBuffer()
      const fileReader = new FileReader()
      const loadNext = () => {
        const start = currentChunk * chunkSize
        const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
      }
      return new Promise((resolve, reject) => {
        fileReader.onload = (e) => {
          spark.append(e.target.result) // Append array buffer
          currentChunk++
          if (currentChunk < chunks) {
            loadNext()
          } else {
            console.log('finished loading')
            const res = spark.end()
            console.info('computed hash', res) // Compute hash
            resolve(res)
          }
        }

        fileReader.onerror = () => {
          reject()
          console.warn('oops, something went wrong.')
        }
        loadNext()
      })
    },
    // 上传前校验 返回false/reject() 不会执行onUpload
    beforeUpload(file) {
      return new Promise((resolve, reject) => {
      	 // console.log(file)
        const acceptType = this.MineTypes.indexOf(file.type) > -1
        if (!acceptType) {
          this.$message.error('不支持上传此类型文件')
          return reject()
        }

        const acceptExt = this.extensions.indexOf(getExt(file.name)) > -1
        if (!acceptExt) {
          this.$message.error('不支持上传此类型文件')
          return reject()
        }

        const passSize = file.size / 1024 / 1024 < 50
        if (!passSize) {
          this.$message.error(this.TipText)
          return reject()
        }
        
        return this.getFileMd5(file).then(fileMd5 => {
          file.fileMd5 = fileMd5
          if (this.form.channel) file.channel = this.form.channel
          return validateFileMd5({ fileMd5 })
        }).then(res => {
          if (res.count > 0) {
            return this.$confirm('该文件已存在, 是否继续上传?', '提示', {
              confirmButtonText: '继续',
              cancelButtonText: '取消',
              type: 'warning'
            })
          } else return true
        }).then(res => {
          res ? resolve() : reject()
        }).catch(e => {
          reject()
        })
      })
    },
    async onUpload(req) {
      // 上传
      const rawFile = {
        status: 'ready',
        name: req.file.name,
        size: req.file.size,
        percentage: 0,
        uid: req.file.uid,
        file: req.file,
        source: CancelToken.source()
      }
      this.fileList.push(rawFile)

      rawFile.status = 'uploading'
      rawFile.percentage = 0
      upload(rawFile.file, (progressEvent) => {
        // Do whatever you want with the native progress event
        rawFile.status = 'uploading'
        rawFile.percentage = Math.floor(progressEvent.loaded / progressEvent.total * 100) || 0
        console.log('上传中:', rawFile.percentage)
      }, rawFile.source.token).then(res => {
        if (res.data) {
          rawFile.reponseData = res.data
          this.changeValue()
          rawFile.status = 'success'
        } else {
          throw Error('res.data')
        }
      }).catch((error) => {
        rawFile.status = 'ready'
        rawFile.percentage = 0
        const index = this.fileList.findIndex(v => v.file.uid === rawFile.file.uid)
        if (index > -1) this.fileList.splice(index, 1)
        // this.$refs.uploadFile.clearFiles()
        this.$message.error('图片上传失败')
        console.log(error)
      }).finally(() => {
        this.loading = false
      })
    },
    onRemove(file, fileList) {
      if (file.status === 'uploading') {
        file.source.cancel('中止上传')
        file.source = CancelToken.source()
      }
      // elementui bug 移除时候fileList得手动移除
      const index = this.fileList.findIndex(v => v.uid === file.uid)
      if (index > -1) this.fileList.splice(index, 1)
      this.changeValue()
    },
    submit() {
      this.$refs.uploadFile.submit()
    },
    handleExceed(files, fileList) {
      this.$message({
        type: 'warning',
        message: '已有文件,请先删除当前已有文件',
        showClose: true
      })
    }
// 中断上传
export const CancelToken = axios.CancelToken // axios的config中提供了一个cancelToken属性,可以通过传递一个新的CancelToken对象来在请求的任何阶段关闭请求。
// export const source = CancelToken.source()

export const upload = (file, onUploadProgress, cancel) => {
  const params = new FormData()
  params.append('file', file) // 字段名称
  params.append('fileMd5', file.fileMd5)

  return axios.post(`/?action=uploads`, params, {
    baseURL,
    withCredentials: true, // send cookies when cross-domain requests
    timeout: 300000, // request timeout
    headers: {
      'Content-Type': 'multipart/form-data', // 类型
      'X-Token': getToken()
    },
    onUploadProgress,
    cancelToken: cancel
  })
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
易购商城是一个基于Vue框架开发的前端毕设项目。在该项目中,我使用了VueVuex、Vue Router、Element UIAxios等技术和库来实现各种功能。 首先,Vue是一种流行的前端框架,它具有响应式的数据绑定和组件化的特性,使得开发者可以轻松构建交互性强、高效的单页面应用。 其次,我使用了Vuex来管理应用的状态。Vuex提供了一种集中式的状态管理方案,帮助我管理和共享全局的数据,使得不同组件之间的通信更加便捷。 Vue Router是Vue官方提供的路由管理库,用于实现页面之间的导航和路由跳。我使用它来定义和管理不同页面之间的跳逻辑,使得用户可以通过URL来访问和导航各个页面。 Element UI是一套基于Vue的桌面端组件库,它提供了丰富的UI组件和样式,使得我可以快速构建出美观和功能完善的界面。 为了与后端进行数据交互,我使用了Axios库。Axios是一个基于Promise的HTTP客户端,可以在前端与后端进行异步数据交互,使得用户可以实现登录、注册、添加购物车、结算等功能。 最后,我还使用了Vue插件vue-echarts和vue-awesome-swiper来实现商品数据的可视化展示和轮播图功能。这些插件都提供了强大且易用的功能,使得易购商城的用户界面更加丰富和吸引人。 总体来说,通过使用VueVuex、Vue Router、Element UIAxios等技术和库,我成功地实现了易购商城的前端开发工作,提供了丰富的功能和良好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值