大家好,欢迎来到IT知识分享网。
一、前言
最近的工作中遇到了一些需要 前端 上传文件的 需求,作为新手程序员的我之前都是 从老的项目中 找到 类似的功能 然后 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( )
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()
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 ); },
五、参考资料和文章
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/158185.html