el-upload中遇到上传失败的图片没有被删除,显示在页面上怎么办?

468 阅读4分钟

一、关于文件存在形式,img地址的前置知识(以图片为例)

当文件在前后端之间进行通讯传递,和文件被获取到,以及文件被展示的时候。它们都是以不同的状态存在的。这就不得不了解文件的类型。
当你通过input获取文件file的时候,你可以通过浏览器的开发者工具打印,看到file的一些属性,比如name,size、type之类的,但是无法看到file的实体。这个时候,你也无法看到去看到文件。
当文件需要进行进行网络传递的时候,我们不会直接上传这个file实体,而是通过formData等方法去转变为二进制格式,进行传递。当然同样的,你在浏览器的开发者工具当中,也看不见这个文件的实体,可以看见它是二进制。 如何被看见?你需要将获取到的file文件,转化为地址的形式,放入到img的地址上才可以。 URL.createObjectURL()这个api,参数为file或者blob对象,可以获取到文件的地址。然后放到img的地址即可。
这样又引出了另一个问题,img地址都可以放入什么类型的

1.img.url类型

(1)base64格式地址
data:image/jpeg;base64,/9j/4AAQSkZJRgABA... 特点:①直接将数据编码到url中,所以地址很长②因为将信息编码到url中,所以请求地址本身,就是请求图片,不需要额外的http请求
(2)blob地址 "blob:example.com/1234-5678-9…" 通过URL.createObjectURL创建,参数为file或者blob对象 const blobUrl = URL.createObjectURL(blob); <通过上传组件,从本地获得的图片地址就是blob地址。
(3)相对路径 "./images/photo.jpg" "../assets/images/photo.jpg" 相对于页面本身的路径,本地开发,有时候直接使用不成功,尤其是动态加载的时候:src 使用require主要是为了加载loader来处理图片,处理动态路径
(4)绝对路径 "example.com/images/phot…" 展示用于cdn加载,下载会有跨域问题

(5)文件协议url // 本地文件路径 "file:///C:/Users/images/photo.jpg" 仅仅使用于本地开发

二、上传过程分析

通常来说,就包括几个步骤,1.通过file类型的input,拿到文件,2.将file文件转化为二进制格式或者base64的格式等,3.将文件转化为地址进行展示,4.通过axios将转化好的二进制文件传递给后端。

(但是在实际开发中,往往不是这样的,后端通常有专门的接口去处理我们上传的文件,然后给我们返回一个在线的地址来进行回显,所以如果我们直接拿着从本地获取到的文件地址进行展示,就会发生文件可能上传失败了,但是我们这里还显示着照片,造成混乱)

所以这里的步骤就改为了这样。
1.通过file类型的input,拿到文件,2.将file文件转化为二进制格式或者base64的格式等,3.通过axios将转化好的二进制文件传递给后端。 4.后端返回绝对路径 5.拿着后端返回的路径,放入到img的url中进行回显。

三、具体使用el-upload

这是具体总结的el-upload钩子的使用,以及哪些情况会触发哪些钩子函数,哪些钩子不会被触发。

image.png

image.png

四、遇见的大坑

就是el-upload除了我们自己指定的fileList,内部还维护了一个uploadFiles的数组,有时候,我们并没有同步fileList,页面当中还是会显示出来我们上传的文件,这是因为uploadFiles数组新增了我们上传的文件,uploadFiles中的文件也会显示出来,所以就会隐身出一个问题,根据我在上传过程分析中,如果上传失败是要不显示这个图片的。 所以我们需要在失败的时候去删除这个图片。

handleProcesschange(data) {
      console.log("handleProcesschange", data);
      const file = data.file;
      // 1.当我们上传图片的时候,获取了文件file
      // 2.如果我们想本地展示图片,可以先将file转换为base64,转化为图片地址,然后进行展示
      // const imageUrl = URL.createObjectURL(file);
      // this.processPicList.push({
      //   name: file.name,
      //   url: imageUrl,
      //   ...file,
      // });
      // 3.如果我们要发给后端,则需要将file转换为formData,然后进行上传
      // 然后通过后端发来的图片地址进行展示
      const form = new FormData();
      form.append("file", file);
      form.append("type", "maintenance");
      fileUpload(form)
        .then((res) => {
          if (res.meta.status === 300) {
            const fileData = res.data.url;
            console.log("fileData", res);
            const obj = {
              name: file.name,
              url: fileData,
              ...file,
            };
            console.log(obj);
            this.processPicList.push(obj);
            this.$message.success("附件上传成功");
          } else {
            let uid = file.uid; // 关键作用代码,去除文件列表失败文件
            let idx = this.$refs.uploadProcess.uploadFiles.findIndex(
              (item) => item.uid === uid
            ); // 关键作用代码,去除文件列表失败文件(uploadFiles为el-upload中的ref值)
            this.$refs.uploadProcess.uploadFiles.splice(idx, 1); // 关键作用代码,去除文件列表失败文件
            this.$message.error(res.msg || "上传失败!");
          }
        })
        .catch((error) => {
          console.log("error", error);
          // this.processPicList.pop();
        });
    },