详解FormData 、Blob、File、FileReader、ArrayBuffer、URL、URLSearchParams对象


一. FormData

利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.

方法:

var formData = new FormData();
formData.append("k1", "v1"); //append()方法的第二个参数可以是File,Blob对象
formData.append("k1", "v2");
formData.get("k1"); // // "v1" 获取key为name的第一个值
formData.getAll("k1"); // ["v1","v2"] 返回一个数组,获取key为name的所有值
formData.set("k1", "1"); //设置修改数据
formData.has("k1"); // true 来判断是否有对应的key值
formData.has("k2"); // false
formData.delete("k1"); //删除数据

根据已有form表单初始化一个formData对象:

// 获取页面已有的一个form表单
var form = document.getElementById("myForm");
// 用表单来初始化
var formData = new FormData(form);
// 我们可以根据name来访问表单中的字段
var name = formData.get("name"); // 获取名字
var psw = formData.get("pw"); // 获取密码
// 当然也可以在此基础上,添加其他数据
formData.append("token","kshdfiwi3rh");

发送一个二进制数据流:

var content = '<a id="a"><b id="b">hey!</b></a>'; 
var blob = new Blob([content], { type: "text/xml"});
formData.append("file", blob);
axios.post('http://demo.api.com/doSomething', formData,
    {
        headers: {
            'Content-Type': 'multipart/form-data'
       }
   }
)

二. Blob

一个Blob对象就是一个包含有只读原始数据的类文件对象。Blob对象中的数据并不一定得是JavaScript中的原生形式。File接口基于Blob,继承了Blob的功能,并且扩展支持了用户计算机上的本地文件。

Blob对象可以看做是存放二进制数据的容器,但要读取里面的二进制数据,需要用FileReader;此外还可以通过Blob设置二进制数据的MIME类型。

/**
* Blob构造函数:
* dataArray:数组,包含了要添加到Blob对象中的数据,数据可以是Int32Array、Uint8Array、Float32Array等,或者连续内存缓冲区ArrayBuffer,ArrayBufferView, Blob,或者 DOMString对象。
* opt:对象,用于设置Blob对象的属性(如:MIME类型)
**/
var blob = new Blob(dataArr:Array<any>, opt:{type:string});
  1. 创建一个装填DOMString对象的Blob对象
var s = '<div>hello</div>'
var blobObj = new Blob([s], {type: 'text/xml'})
  1. 创建一个装填ArrayBuffer对象的Blob对象
var abf = new ArrayBuffer(8)
var blobOjb = new Blob([abf], {type: 'text/plain'})
  1. Blob.slice()
    此方法返回一个新的Blob对象,包含了原Blob对象中指定范围内的数据,利用此发放可以实现大文件的分片上传
/**
* start:开始索引,默认为0
* end:截取结束索引(不包括end)
* contentType:新Blob的MIME类型,默认为空字符串
**/
Blob.slice(start:number, end:number, contentType:string)
  1. Canvas.toBlob()
    canvas转为blob对象
  2. 实现url下载文件
    window.URL对象可以为Blob对象生成一个网络地址,结合a标签的download属性,可以实现点击url下载文件
function createDownload(fileName, content){
    var blob = new Blob([content]);
    var link = document.createElement("a");
    link.download = fileName;
    link.href = URL.createObjectURL(blob); //可以直接当作image的src属性来显示图片
    link.click()
}

三. File

File是Blob的子类,比blob主要多出一个name的属性。

我们常用的文件选择标签<inout type="file" />元素就拥有一个files属性,这个files就是File类型

var input = document.querySelector('input[type=file]');
console.log(input.files) // FileList {0: File(3044232), length: 1}

四. URL

除了可以使用base64字符串作为内容的DataURI将一个文件嵌入到另外一个文档里,还可以使用URL对象。URL对象用于生成指向File对象或Blob对象的URL

实例属性:

var url = new URL(location.href)
url.href //包含完整 URL 的DOMString
url.protocol //包含 URL 协议名的DOMString,末尾带 ':'。
url.host //包含 URL 域名,':',和端口号的DOMString
url.hostname //包含 URL 域名的DOMString
url.port //包含 URL 端口号的DOMString
url.pathname //以 '/' 起头紧跟着 URL 文件路径的DOMString
url.search //以 '?' 起头紧跟着 URL 请求参数的DOMString
url.hash //以 '#' 起头紧跟着 URL 锚点标记的DOMString
url.username //包含在域名前面指定的用户名的DOMString
url.password //包含在域名前面指定的密码的DOMString
url.origin //返回一个包含协议名、域名和端口号的DOMString
url.searchParams //返回一个用来访问当前 URL GET 请求参数的URLSearchParams对象

静态方法:

  • URL.createObjectURL()
    该方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
var objectURL = URL.createObjectURL(blob);

blob是用来创建 URL 的 File 对象或者 Blob 对象​

  • URL.revokeObjectURL()
    该方法用来释放一个之前通过调用 URL.createObjectURL() 创建的已经存在的 URL 对象。当你结束使用某个 URL 对象时,应该通过调用这个方法来让浏览器知道不再需要保持这个文件的引用了。
window.URL.revokeObjectURL(objectURL);

objectURL是一个 DOMString,表示通过调用 URL.createObjectURL() 方法产生的 URL 对象

五. URLSearchParams

URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。
方法:

  • URLSearchParams.append() 插入一个指定的键/值对作为新的搜索参数。
  • URLSearchParams.delete() 从搜索参数列表里删除指定的搜索参数及其对应的值。
  • URLSearchParams.entries() 返回一个iterator可以遍历所有键/值对的对象。
  • URLSearchParams.get() 获取指定搜索参数的第一个值。
  • URLSearchParams.getAll() 获取指定搜索参数的所有值,返回是一个数组。
  • URLSearchParams.has() 返回Boolean判断是否存在此搜索参数。
  • URLSearchParams.keys() 返回iterator此对象包含了键/值对的所有键名。
  • URLSearchParams.set() 设置一个搜索参数的新值,假如原来有多个值将删除其他所有的值。
  • URLSearchParams.sort() 按键名排序。
  • URLSearchParams.toString() 返回搜索参数组成的字符串,可直接使用在URL上。
  • URLSearchParams.values() 返回iterator此对象包含了键/值对的所有值。
    基本用法:
var paramsString = "https://www.baidu.com?topic=api&target=bank"
var searchParams = new URLSearchParams(paramsString);

searchParams.has('topic') // true
searchParams.get('topic') // "api"
searchParams.get('target') // "bank"
searchParams.getAll('topic') // ["api"]

searchParams.get('foo') // null,注意Firefox返回空字符串
searchParams.set('foo', 2);
searchParams.get('foo') // 2

searchParams.append('topic', 'webdev');
searchParams.toString() // "q=URLUtils.searchParams&topic=api&foo=2&topic=webdev"

searchParams.append('foo', 3);
searchParams.getAll('foo') // [2, 3]

searchParams.delete('topic');
searchParams.toString() // "q=URLUtils.searchParams&foo=2&foo=3"

在一些场景里使用axios发送数据时若需要以application/x-www-form-urlencoded格式发送数据,在浏览器端可以用URLSearchParams的实例当作POST数据发送,所有数据都会URL编码。(请注意,由于URLSearchParams支持性不好,可以使用polyfill来转换,可以在入口文件引入

import 'url-search-params-polyfill';

在node环境里可以使用querystring模块进行编码

var querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' });

DOM 的 a 元素节点的 searchParams 属性,就是一个 URLSearchParams 实例。

var a = document.createElement('a');
a.href = 'https://example.com?filter=api';
a.searchParams.get('filter') // "api"

URLSearchParams 还可以与 URL 接口结合使用:

var url = new URL(location);
var foo = url.searchParams.get('foo') || 'somedefault';

六. FileReader

我们知道Blob对象只是二进制数据的容器,本身并不能操作二进制,FileReader对象就是专门操作二进制数据的,FileReader主要用于将文件内容读入内存,通过一系列异步接口,可以在主线程中访问本地文件。

创建实例:

var reader = new FileReader();

方法(入参都是FileBlob对象)

  • reader.abort() 终止文件读取操作
  • reader.readAsArrayBuffer(file) 异步按字节读取文件内容,结果用ArrayBuffer对象表示
  • reader.readAsBinaryString(file) 异步按字节读取文件内容,结果为文件的二进制串
    reader.readAsDataURL(file) 异步读取文件内容,结果用data:url(即Base64格式)的字符串形式表示
  • reader.readAsText(file, encoding) 异步按字符读取文件内容,结果用字符串形式表示

事件名称

  • onabort 当读取操作被中止时调用
  • onerror 当读取操作发生错误时调用
  • onload 当读取操作成功完成时调用
  • onloadend 当读取操作完成时调用,不管是成功还是失败
  • onloadstart 当读取操作将要开始之前调用
  • onprogress 在读取数据过程中周期性调用

它们在实际场景中的一些应用

  1. 上传图片后直接显示出来,而不用先经过后台
var input  = document.getElementById("file"); //input file
input.onchange = function(){
    var file = this.files[0];
    if(!!file){
        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function(){
            //读取完毕后输出结果
           document.getElementById("file_img").src = reader.result //显示上传的图片
           console.log(reader.result);
        }
    }
}
  1. 图片转二进制Blob
    在实际文件上传中,将用户选择的图片读取为ArrayBuffer并保存到新的Blob对象中,二进制的方式传参比直接传图片效率更高)
input.addEventListener('change', function() {
  var file = this.files[0],
      fr = new FileReader(),
      blob;
  fr.onload = function() {
      blob = new Blob([this.result]);
      var formdata = new FormData()
      formdata.append('file', blob)
  };
  fr.readAsArrayBuffer(file)
});
  1. 图片Image转Base64
function getImgToBase64(url,callback){
    var canvas = document.createElement('canvas')
    var ctx = canvas.getContext('2d')
    var img = new Image
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img,0,0);
        var dataURL = canvas.toDataURL('image/png'); //base64格式
        callback(dataURL);
        canvas = null;
    };
    img.src = url;
}
  1. Base64转为BlobFile
function base64ToBlob(base64){
    var arr = base64.split(',')
    var mime = arr[0].match(/:(.*?);/)[1]
    var bytes = atob(arr[1])      //对用base64编码过的二进制进行解码  
    var n = bytes.length
    var u8arr = new Uint8Array(n)
    while(n--){
        u8arr[n]=bytes.charCodeAt(n);   //将编码转换成Unicode编码
    }
    return new Blob([u8arr], {type: mime})
    //or: return new File(u8arr], {type:mime})  //base64转换为文件

   //以二进制的方式传参:
    var formdata = new FormData()
    formdata.append('file', new Blob([u8arr], {type: mime}))
    xhr.send(formdata)
}

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

推荐阅读更多精彩内容