PC端 vue + element 实现上传附件并下载[流水账]

上传:

遇到的问题:

  • 动态赋值 上传的地址action 取值总是慢一步,拿到的是上次的值。

解决方案:

针对问题1:采用延时,目前使用的是 nextTick

代码部分:单文件上传

// template
<template>

          <el-upload
            ref="attachmentRef"
            drag
            accept=".jpg,
                .jpeg,
                .png,
                .gif,
                .rar,
                .txt,.zip,.doc,.ppt,.xls,.xlsx,.docx,.pdf,.JPG,.JPEG,.PDF"
            :headers="headers"
            :data="{extension: extension}"
            :action="buildUploadUrl"
            :file-list="fileList"
            :auto-upload="false"
            :before-upload="handleBeforeUpload"
            :on-change="handleChange"
            :on-success="handleSuccess"
            :on-error="handleError"
            :on-remove="handleRemove"
          >
            <i class="el-icon-upload" />
            <div class="el-upload__text">
                将文件拖到此处,或 <em>点击上传</em>
            </div>
          </el-upload>

</template>

// data
data () {
    return {
      headers: {}, // 可放置接口所需要的 token
      fileList: [], // 已上传的文件列表
      extension: '', // 上传文件的后缀名
      buildUploadUrl: '', // 接口地址
      extension: '' // 文件后缀名     
    }
},

// methods

methods: {
    // 处理文件回显,可在 created 里调用该方法
    handleEditFileList () {
        this.fileList = [] // 替换为 后端返回的数据
    },

    handleBeforeUpload (file) {
      // 校验格式
      let allowType = ['jpg',
        'png',
        'rar', 'txt', 'zip', 'doc', 'ppt', 'xls', 'xlsx', 'pdf', 'docx', 'gif']
      let testMsg = file.name.substring(file.name.lastIndexOf('.') + 1) // 文件后缀名
      const isAllow = allowType.includes(testMsg)
      if (!isAllow) {
        this.$message({
          message: '不支持当前上传文件的格式!',
          type: 'warning'
        })
        return false
      }

      // 校验文件大小。不能大于 5M
      let maxSize = 5
      let isLessThanMaxSize = file.size / 1024 / 1024 < Number(maxSize)
      if (!isLessThanMaxSize) {
        this.$message.error(`附件大小不能超过 ${maxSize}MB!`)
      }

      return isLessThanMaxSize
    },
    
    handleChange (file) {
      if (file.status === 'ready') {
        // 准备上传
        this.extension = file.name.split('.').pop() // 文件后缀
        this.buildUploadUrl = url + `?extension=${this.extension}` // 接口地址拼接文件后缀
        
        // 这里记录一下坑
        // 如果不用 nextTick,action总是慢一步,第一次上传接口地址就为空
        // 因为需要动态获取的 文件后缀,如果直接上传,action 总是上一次的值(第二次选的txt还是用的第一次的 png)
        // submit 方法比 action赋值快一步,这里做下延时

        // 延迟
        this.$nextTick(() => {
          this.$refs.attachmentRef.submit()
        })
      }
    },

    handleSuccess (response, file) {
      if (!response.isOk) {
        this.$refs.attachmentRef.clearFiles()
        this.$message.error(response.message || '上传失败~')
        return
      }

      this.url = response.content.url
      this.id = response.content.id
      this.fileList = [file]
    },

    handleError () {
      this.$refs.attachmentRef.clearFiles()
      this.$message.error('上传附件失败~')
    },
    handleRemove (file) {
      if (file.status === 'success') {
        this.url = ''
        this.id = null
      }
    }
}

下载:

遇到的问题:

  • <a href="url" download="xxx.txt">下载</a> 遇到 文本类型 的文件下载不了。
  • window.location.href = url 下载方式,遇到 图片、文本、pdf 类型的文件会直接打开,不会下载。
  • createObjectURL() 的时候,可能后端返回的直接就可以用,不用再 new Blob[res.data] 了。
    • 如:直接 createObjectURL(res.data),不用 createObjectURL(new Blob([res.data]))

尝试的解决方式:

  • 采用 axios 的读取文件的方式下载,注意传 responseType: 'blob
  • handleDownUrl () {
        if (this.url) {
            // 后端返回的是 http,网站是 https,不替换会造成跨域,如果一致,可将这段删除
            let locationUrl = ''
            if (location.protocol === 'https' || location.protocol === 'https:') {
              locationUrl = this.url.replace('http://', 'https://')
            } else {
              locationUrl = this.url
            }
    
            axios.get(locationUrl, {
              responseType: 'blob'
            }).then(res => {
              let blob = res.data
              let url = window.URL.createObjectURL(blob)
    
              let a = document.createElement('a')
              a.style.display = 'none'
              a.href = url
              a.download = this.value.url.split('/').pop()
              document.body.appendChild(a)
              a.click()
    
              window.URL.revokeObjectURL(a.href)
              document.body.removeChild(a)
            })
          }
    }

    先后尝试了,a链接下载window.location.href 下载,均不行,换了上述以为行了,于是发到了测试环境测试,测试环境也测过了,以为万事大吉了。

  • 上线

        报了一个大错误,麻了 

 应该还是跨域的问题,因为紧急情况,替换了 复制链接(vue-clipboard2) 自行到浏览器下载的方案。

大家如果有解决方案,欢迎交流~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值