js文件上传中遇到的知识点

前言

在前端开发中,我们经常遇到上传文件的需求,以前都是用到时再找资料,但总是感觉对这块不熟,最近翻资料学习了一下,记录一下。

本文中涉及的知识点有:FileList对象,Blob对象,File对象,URL对象、FormData对象等。

本文参考网道,总结而来。另外,强烈推荐网道,可以去网道的官方看看,是阮一峰大神发起的项目,提供互联网开发文档,文档非常全面易懂。

FileList 对象

FileList对象,是一个像数组的对象,拥有length属性和item()方法,同时,它的每一项都是File对象。

input 标签,将type设为file,之后得到的files属性就是一个FileList对象。

    // html
    <input type="file" accept="image/*" id="fileDiv" />
    
    // js
    var fileInput = document.getElementById('fileDiv');
    var fileListObj = fileInput.files;
    console.log(fileListObj instanceof FileList); // true
    console.log(fileListObj.length); // 0
    

Blob 对象

blob 对象表示1个二进制文件的数据内容。blob对象和arraybuffer区别是,blob对象用于操作二进制文件,arraybuffer用于操作内存。

blob 对象拥有2个属性和1个方法,分别是size(单位是字节)、type属性和slice()方法。

File 对象

File 对象是一种特殊的Blob 对象。它在继承了size、type属性外,还同时有name、lastModified、lastModifiedDate等几个属性。

FileList 对象中的每一项都是File 对象。

拿到File 对象之后就要进行操作,下面是操作。

URL 对象

URL.createObjectURL(file) 允许为File 对象创建一个临时链接,

 // 例如我们可以在选中了图片之后,展示到页面上
 // html
 <input type="file" accept="image/*" id="fileDiv" onchange="getFile(this.files[0])" />
 <img id="myimg" />
 
 // js
 function getFile(file){
    var urlObj = URL.createObjectURL(file);
    var myimg = document.getElementById('myimg');
    myimg.src = urlObj;
    console.log(urlObj);
 }

 /**
 * 输出如下:
 * blob:http://127.0.0.1:8848/1410c491-27e2-47fa-8198-1d1ea4eece46
 */

FileReader 对象

FileReader 对象的属性和方法比较多,属性中比较重要的是result,方法中比较重要的是

  • readAsText(file[,code]) 将文件读取成为文本数据,第二个参数默认采用utf-8编码,返回到FileReader的result属性中
  • readAsArrayBuffer(file) 将文件读取成为内存数据,返回到FileReader的result属性中
  • readAsBinaryString(file) 将文件读取成为原始二进制数据,返回到FileReader的result属性中
  • readAsDataURL(file) 将文件读取成为base64字符串,返回到FileReader的result属性中
    // 例如,将文件读取为base64数据,赋值给Img.src属性
    // html
    <input type="file" accept="image/*" id="fileDiv" onchange="getFile(this.files[0])" />
    <img id="myimg" />
    
    // js
    function getFile(file){
        var myimg = document.getElementById('myimg');
        var reader = new FileReader();
        reader.onload = function(){
            myimg.src = reader.result;
        }
        reader.readAsDataURL(file);
    }

FileReader 对象的所有属性和方法可以参考这里,这里就不再列出来了。

FormData 对象

在早期的互联网时候,提交数据都是用表单。表单提交数据有些缺陷,例如无法校验表单数据,会刷新整个页面等。随着Ajax的兴起,页面表单提交数据慢慢退出历史舞台,但有时上传文件时我们偶尔会用到表单提交数据。

在调用构造函数new FormData(form)构造formdata对象时需要传入form节点,如果不传入,则默认构建空表单。如果传入,则按照key=value的时候构建表单。

    // html
    <form id="myform">
        <input name="username" type="text" placeholder="请输入用户名" />
        <br />
        <br />
        <input name="password" type="password" placeholder="请输入密码" />
        <br />
        <br />
        <input name="age" type="number" placeholder="请输入年龄" />
    </form>
    <br />
    <input type="button" value="创建表单" id="mybtn" />
 
    // js
    var btn = document.getElementById('mybtn');
    btn.onclick = function(){
        var formNode = document.getElementById('myform');
        var formdata = new FormData(formNode);
        for(var pair of formdata.entries()){
            console.log(pair[0] + ': ' + pair[1]);
        }
    }

可以看看效果图


formdata.png

FormData 对象主要的方法有:

  • get(key) 返回指定key的键值
  • getAll(key) 返回指定key的所有键值,如果有多个的话。(注意: set()方法会覆盖同名键值对,append()方法则不会覆盖),返回值是1个数组
  • set(key, value) 设置键值对
  • delete(key) 删除键值对
  • append(key, value) 在formdata对象后边添加键值对,如果第二个参数是文件,还可以使用第三个参数,表示文件名。
  • has(key) 返回布尔值,表示是否具有该键名的键值对。
  • keys() 返回一个遍历器对象,用于for...of循环遍历所有的键名。
  • values() 返回一个遍历器对象,用于for...of循环遍历所有的键值。
  • entries() 返回一个遍历器对象,用于for...of循环遍历所有的键值

cavas压缩图片

cavas压缩图片其实很简单,无非就是几个步骤:
1、选择图片,判断图片是否大于2M(用File对象的size进行判断,size的单位是字节);
2、用FileReader对象读取文件成base64,
3、然后创建Image对象,赋值src属性,在Image对象加载完成的回调里创建cavas并绘制图片(根据图片是否大于2M动态调整画布大小);
4、将cavas转成blob,拼在formdata中用ajax上传。


// 选择图片
$("#idcard_reverse_input").change(function (e) {

        var loading = weui.loading('上传中...');
        // 判断是否大于2M,大于2M需要压缩图片后再上传
        var result = e.target.files[0].size > 2*1024*1024;
        var fileObj = e.target.files[0]; //上传文件的对象

        var reader = new FileReader();
        reader.readAsDataURL(fileObj);
        reader.onload = function(er) {
            var image = new Image()
            image.src = er.target.result;
            image.onload = function() {
                var canvas = document.createElement('canvas'), 
                context = canvas.getContext('2d'),
                imageWidth = result?image.width * 0.1:image.width,    //动态计算画布大小
                imageHeight = result?image.height * 0.1:image.height;
                               
                // 将画布缩小为图片的1/10,然后将图片缩小画入画布中,之后到处画布就能达到压缩图片的效果。
                canvas.width = imageWidth;
                canvas.height = imageHeight;
                context.drawImage(image, 0, 0, imageWidth, imageHeight);
                
                canvas.toBlob(function(blob){
                    uploadReverse(blob,loading,true)
                },'image/jpeg',0.8)
            }
        }
    });
    
    function uploadReverse(fileObj,loading,isReverse){
        var time = new Date().getTime();
        var str = 'code=G1&time=' + time;
       // fileSecret是个全局变量,是个秘钥
        var apisign = md5(fileSecret + str);

        // 构造表单数据
        var formData = new FormData();
        var imgName = isReverse ? 'reverse.png' : 'front.png'
        formData.append("file",fileObj,imgName);
        formData.append("apisign", apisign);
        formData.append("time", time);
        formData.append("code", 'G1');
        $.ajax({
            url : 'http://example.baidu.com/upload',
            type:'post',
            data: formData,
            contentType: false,
            processData: false,
            success:function(res){
                if(res.status != '1'){
                    weui.alert(res.info);
                    return ;
                }
                // 上传成功
            },
            fail : function(){
                weui.alert('上传失败,请重新选择图片上传!')
            },
            complete:function(){
                loading.hide()
            }
        })
    }

总结

这篇文章到这里也就结束了,这篇文章包含了一些浏览器中提供的对象,可以看到都是很简单的内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容