+
 新版

后端开发已经绝望,来个前端大佬帮助,el-upload上传出现粘贴出现多个图片的问题

sprouting 发布于 2022/08/31 08:51
阅读 2K+
收藏 0
vue

问题是这样的,有这么个需求,使用el-upload组件做上传的时候,需要文件和表单同时上传,同时,上传组件支持拖拽、支持截图复制粘贴(注意,这里的粘贴网上很多代码是直接复制图片文件,然后进行粘贴,要的不是这种,而是类似QQ截图后,直接粘贴,将剪切板中的图片粘贴到上传组件中),现在这一块的问题都基本解决了,但出现一个奇怪的bug,粘贴之后,我将这个图片删除,再次复制,就会将历史的图片也粘贴进去,假如我之前上传5张,然后全部删掉,再次粘贴,5张图片又全部出现+现在粘贴的,一共6张

对代码进行了查询,实在没找到问题

组件代码如下:

核心方法

handlePaste

问题应该出在

this.upload.fileList.push({"name": blob.name, "url": objectURL})

这一块,我怀疑还有其他地方做了上传,下面是bug的复现。求解各位

最后,最后,还有一个问题不太清楚,因为这一块都是和表单一起上传,我想知道,最终上传的时候,我去哪里拿这些文件,难道要从 fileList 中找到文件 url ,然后读取出来吗?还有以后做编辑的时候,这个图片回显是放到fileList中回显,但怎么才能避免再次更新图片file呢?靠加状态来检测图片是否被更换?

<template>

  <div>
    <!--drag 拖曳上传,去掉就是正常的上传-->
    <el-upload
      action="#"
      :accept="upload.accept"
      :auto-upload="upload.autoUpload"
      :on-change="imageChange"
      multiple
      drag
      :on-remove="onRemove"
      :on-exceed="handleExceed"
      :limit="upload.limit"
      :show-file-list="upload.showFileList"
      :list-type="upload.pictureCard"
      :class="{hide: upload.hideUploadAdd}"
      :file-list="upload.fileList">

      <!--上传按钮-->

      <!--拖曳上传的提示文字-->
      <div class="el-upload__text">将图片拖到此处,或<em>点击上传</em></div>
      <!--普通上传-->
      <i class="el-icon-plus"></i>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png/jpeg/gif文件</div>
    </el-upload>
  </div>

</template>

<script>
  export default {
    // 对 el-upload 的封装。单图片上传,支持截图粘贴、支持图片的预览、拖曳上传
    name: "SinglePictureUploadScreenshot",
    // 父子组件传值
    props:{

    },
    data(){
      return {
        // 上传配置
        upload: {
          // 上传的文件
          fileList: [],
          // 关闭自动上传
          autoUpload: false,
          // 是否显示上传文件列表
          showFileList: true,
          // 限制的图片类型
          accept: ".jpg,.jpeg,.png,.gif",
          // 照片picture-card展示的方式
          pictureCard: 'picture-card',
          // 最多一次上传1张图片,这里实际没啥用,用来做后续扩展的
          limit: 1,
          // 是否隐藏添加框,当添加数量达到后隐藏继续添加的按钮
          hideUploadAdd: false,
        },
      }
    },
    methods: {
      /**
       * 监听粘贴
       * 2022年8月31日01:42:07 无法解决粘贴后的多次上传图片问题
       * @param event 复制事件
       */
      handlePaste(event){
        // 上传文件>=限制个数时隐藏上传组件
        // if (this.upload.fileList.length >= this.upload.limit) {
        //   this.upload.hideUploadAdd = true
        //   this.$message.warning("图片最大只允许上传" + this.upload.limit + "张!");
        //   return
        // }
      // @paste.native="handlePaste"

        let items = event.clipboardData.items[0]
        if(items.type.includes('image')) {
          let blob = items.getAsFile()
          let objectURL = URL.createObjectURL(blob);
          console.log(blob)
          console.log(objectURL)
          // 添加到列表中
          this.upload.fileList.push({"name": blob.name, "url": objectURL})
          // this.upload.fileList.push({url: objectURL})
        }
      },

      /**
       * 每次选择文件都会触发函数,可以用来前端删除和添加照片
       */
      imageChange(file, fileList){
        const isLt20M = file.size / 1024 / 1024 < 20;
        if (!isLt20M) {
          this.$message.error("上传图片大小不能超过 20MB!");
          fileList.splice(-1, 1);
        } else {
          this.upload.fileList = fileList;
        }
        // 上传文件>=限制个数时隐藏上传组件
        if (fileList.length >= this.upload.limit) {
          this.upload.hideUploadAdd = true
        }
      },
      /**
       * 预览查看图片
       */
      onPreview(file){
        this.upload.dialogImageUrl = file.url
        this.upload.dialogVisible = true
      },
      /**
       * 文件添加超过限制进行过滤
       * @param files
       * @param fileList
       */
      handleExceed(files, fileList) {
        this.$message.warning(`不能继续添加图片文件`);
      },
      /**
       * 删除文件的方法
       */
      onRemove(file, fileList){
        console.log("file", file)
        console.log("fileList", fileList)
        // 上传文件>=限制个数时隐藏上传组件
        if (fileList.length >= this.upload.limit) {
          this.upload.hideUploadAdd = true;
        } else {
          this.upload.hideUploadAdd = false;
        }
      },
    },
    mounted(){
      // 监听 ctrl+v键盘事件
      document. addEventListener ( 'paste' , (event)  =>  {
        this.handlePaste(event)
      });
    }
  }
</script>


<style scoped>


</style>

<style >

  /*隐藏掉新的添加框,注意,要将style上传 scoped 去掉*/
  .hide .el-upload--picture-card {
    display: none;
  }

  /*拖曳上传的样式,比之前的框小很多*/
  .el-upload .el-upload-dragger {
    width: 250px;
    height: 150px;
  }
  .el-upload .el-upload-dragger .el-icon-upload {
    margin: 20px 0 16px;
  }

</style>

 

加载中
0
单手开法拉利
单手开法拉利

fileList删除的时候,没有清空?

sprouting
sprouting
看了官方文档,也进行了日志打印,删除的时候这里不需要手动去清理的,会自动删除
0
发财火车
发财火车

我也是醉了,就不能换个做法,每次拖动的时候,就上传,单张上传,绑定一个页面id,删除的时候,也是删除一个,相当于临时文件,最终上传的时候,就用绑定id去加载文件,文件当然上传在文件中心了,若果页面不保存,设置一个过期时间,将上传的这些垃圾文件清楚掉,还非要纠结一次传完

sprouting
sprouting
这问题现在其实换个方法也能做,但我现在就纳闷了,为啥原因?
0
sprouting
sprouting

最终的解决方案

/**
 * 文件列表移除文件时的钩子
 * 注意,这里的 fileList 是已经被处理过的数据,实际的 this.upload.fileList 里面的东西还没有被删除,这里很奇怪,如果是正常的上传走的逻辑,是会
 * 进行删除处理,复制的好像就不行
 */
onRemove(file, fileList){
  // 删除最后一个元素,返回的是删除掉的数据
  let fileArray = this.upload.fileList.pop()

  // 上传文件>=限制个数时隐藏上传组件
  if (fileList.length >= this.upload.limit) {
    this.upload.hideUploadAdd = true;
  } else {
    this.upload.hideUploadAdd = false;
  }
},
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部