前端附件上传的一点理解总结

一、前言

最近的工作中遇到了一些需要 前端 上传文件的 需求,作为新手程序员的我之前都是 从老的项目中 找到 类似的功能 然后 CV 过来,但我也知道这样肯定是不能取得什么真正进步的,于是我在网上浏览了许多文章,并得到了一些自己的感悟,在此记录下来,当然我所领悟的内容 很有可能会存在 许多误解。还是希望路过的大佬们能够 指正我的问题,让我知道自己错在了什么地方。
在我看过的文章里比较主流的 前端 文件上传 方法,就是使用 FormData 对象来实现附件的上传。
原因是,前端在使用 post 请求提交数据的时候,主要都是 将要传输的数据 编码为 application/json 和 application/x-www-form-urlencoded,两种形式来进行 传输。
但 文件类型,也就是 File 类型和 Blob类型(也就是 二进制对象) 类型 的数据,再进行 传输时,会出现 数据丢失的问题。

传输 File 和 Blob 类型的数据,我们需要将 数据 编码为** multipart/form-data ** 类型。

我们可以通过 FormData 对象,来实现这种编码。

*注:multipart/form-data 的大体 样式,就是 一个 对象中 包含着许多 length为 2 的数组 (其本质类似于键值对)。
这些数组,第一个元素是 键名 key ,第二个是 键值 value,但 他们都是字符串的形式。
大体就是这个样子 [‘key’,‘value’]
*

二、先来了解 FormData

1、构造函数:

const obj = new FormData()

console.log('FormDataobj---', obj)

创造一个 FormData 的实例对象

在这里插入图片描述

2、内置方法

①:FormData.append( )

这个方法是,向 FormData 对象中,添加新的数据(当然还要是 key/value 形式的)。
eg:


    obj.append('keyName1','value1')
    console.log('FormDataobj---', obj.getAll('keyName1'))

现在打印,obj 的话 还是 像刚创建好的时候一样,但我们可以先借助 后面的方法,查看其中的内容

在这里插入图片描述

可见,数据被我们添加进去了。

同时,如果添加了 key 相同的数据, 也会再生成一条新的数据,并不会 覆盖掉原本的数据。


    obj.append('keyName1','value1')
    obj.append('keyName1','value2')
    console.log('FormDataobj---', obj.getAll('keyName1'))

在这里插入图片描述

②:FormData.delete()

从 FormData 对象中 删除 一个 键值对。(参数就是 删除目标的 key)

③:FormData.entries()

返回一个包含所有键值对的iterator对象(迭代器)。

通过 for…of 形式,就可以遍历这个 iterator对象 中所有的键值对。

    const obj = new FormData();
   
    obj.append('keyName1','value1')
    obj.append('keyName1','value2')
    obj.append('keyName3','value3')
    const iteratorObj = obj.entries()
    for( var key of iteratorObj ) {
      console.log('key---', key)
    }

如图所示:
在这里插入图片描述

④:FormData.get()

返回在 FormData 对象中与给定键关联的第一个值。也就是 如果一个 key 对应多个 value,
使用这个方法,只会返回第一个 value

    obj.append('keyName1','value1')
    obj.append('keyName1','value2')
    obj.append('keyName1','value3')
    obj.append('keyName3','value3')
    console.log('key---', obj.get('keyName1'))

在这里插入图片描述

⑤:FormData.getAll()

返回一个包含 FormData 对象中与给定键关联的所有值的数组。这次会返回 所有 关联键值

在这里插入图片描述

⑥:FormData.has()

返回一个布尔值表明 FormData 对象是否包含某些键。(参数也是 key)

⑦:FormData.keys()

返回一个包含所有键的iterator对象。 (只有 键名,没有键值)

⑧:FormData.values()

返回一个包含所有值的iterator对象。

⑨:FormData.values()

给 FormData 设置属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值。(除了 覆盖相同 key 的value,其他 与 .append() 方法相同)

三、使用FormData 来进行文件传输

//事件载体
<div class="" @click="testUpload()" id="input"></div>


---------------------------------------

// 基本方法


    testUpload() {
        const inputFile = document.createElement("input");
        inputFile.type = "file";
        inputFile.style.display = "none";
        document.body.appendChild(inputFile);
      
      // 手动触发,前面创建的  type 为 file 的input 标签,就可以唤醒 电脑本地的文件夹。
        inputFile.click();
      
      // 给新创建的标签 添加的侦听,是用来  侦听,我们 选择要上传的目标文件的 这个事件的。
      // 其中选中的 文件,会被保存在我们 创建的 input 标签的 fiels 下。
      // 我这里写的仅仅是最基本的  文件传输,  还可以添加各种限制,比如,通过 截取file 的后缀名 加以判断,来限制 支持传输的文件种类。
        inputFile.addEventListener("change", function () {
            const file = inputFile.files[0];
            const formData = new FormData();
        
        // 将选中的文件,通过 FormData() 转码为 multipart/form-data 类型,进行网络 传输
            formData.append("file", file);
            window.request({
                url: "xxx/xxx",
                data: formData,
                success: (res) => {},
                finally: () => {},
            });
         });
    },


四、使用 Element UI 提供的 组件进行 文件传输


    <el-upload
              class=""
              
              //  传输文件的目标地址
              action=""
              
              //支持多选
              multiple
              
              // 双向绑定 项目中的目标文件,       选中的文件会存在这里
              :file-list="fileList"
              
              //上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
              :before-upload="beforeAvatarUpload"
              
                //文件上传成功时的钩子
              :on-success="handleSuccess"
              :show-file-list="false"
            >
            // 这里  内嵌的  我估计也是一个  类似于  FormData 的文件上传途径,通过点击实现上传。
              <div style="display: flex">
                <el-button
                  style="margin-right: 10px"
                  type="primary"
                  plain
                  >上传</el-button
                >
            </div>
   </el-upload>



-------------------------------------------------------------------------

// 相关方法钩子

// 在此处  对  要传输的文件的类型 , 以及文件大小  做判断
 beforeAvatarUpload(file, fileList) {
      var testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);
      const extension = testmsg === "xls";
      const extension2 = testmsg === "xlsx";
      const extension3 = testmsg === "psd";
      const extension4 = testmsg === "png";
      const extension5 = testmsg === "jpg";
      const extension6 = testmsg === "docx";
      const extension7 = testmsg === "pdf";
      const extension8 = testmsg === "txt";
      const extension9 = testmsg === "zip";
      const extension10 = testmsg === "mp4";
      const extension11 = testmsg === "doc";
      const extension12 = testmsg === "ppt";
      const extension13 = testmsg === "pptx";
      const extension14 = testmsg === "rar";
      const extension15 = testmsg === "XLS";
      const extension16 = testmsg === "XLSX";
      const extension17 = testmsg === "PSD";
      const extension18 = testmsg === "PNG";
      const extension19 = testmsg === "JPG";
      const extension20 = testmsg === "DOCX";
      const extension21 = testmsg === "PDF";
      const extension22 = testmsg === "TXT";
      const extension23 = testmsg === "ZIP";
      const extension24 = testmsg === "MP4";
      const extension25 = testmsg === "DOC";
      const extension26 = testmsg === "PPT";
      const extension27 = testmsg === "PPTX";
      const extension28 = testmsg === "RAR";
      const extension29 = testmsg === "jpeg";
      const isLt2M = file.size / 1024 / 1024 < 100;
      if (
        !extension &&
        !extension2 &&
        !extension3 &&
        !extension4 &&
        !extension5 &&
        !extension6 &&
        !extension7 &&
        !extension8 &&
        !extension9 &&
        !extension10 &&
        !extension11 &&
        !extension12 &&
        !extension13 &&
        !extension14 &&
        !extension15 &&
        !extension16 &&
        !extension17 &&
        !extension18 &&
        !extension19 &&
        !extension20 &&
        !extension21 &&
        !extension22 &&
        !extension23 &&
        !extension24 &&
        !extension25 &&
        !extension26 &&
        !extension27 &&
        !extension28 &&
        !extension29
      ) {
        await this.$message({
          message: "不支持此格式文件!",
          type: "warning",
        });
        throw new Error('Invalid state!');
      }
      if (!isLt2M) {
        await this.$message({
          message: "传输文件大小不能超过 100MB!",
          type: "warning",
        });
        throw new Error('Invalid state!');
      }
      // 全部满足的情况下,返回  1  否则  返回 0 阻止本次 传输
      return (
        (extension ||
          extension2 ||
          extension3 ||
          extension4 ||
          extension5 ||
          extension6 ||
          extension7 ||
          extension8 ||
          extension9 ||
          extension10 ||
          extension11 ||
          extension12 ||
          extension13 ||
          extension14 ||
          extension15 ||
          extension16 ||
          extension17 ||
          extension18 ||
          extension19 ||
          extension20 ||
          extension21 ||
          extension22 ||
          extension23 ||
          extension24 ||
          extension25 ||
          extension26 ||
          extension27 ||
          extension28 ||
          extension29) &&
        isLt2M
      );
    },









五、参考资料和文章

Form对象浅谈
FormData 官方文档

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值