在一般的Web开发中,很少会用到Blob,但Blob可以满足一些场景下的特殊需求。Blob,Binary Large Object的缩写,代表二进制类型的大对象。Blob的概念在一些数据库中有使用到,例如,MYSQL中的BLOB类型就表示二进制数据的容器。在Web中,Blob类型的对象表示不可变的类似文件对象的原始数据,通俗点说,就是Blob对象是二进制数据,但它是类似文件对象的二进制数据,因此可以像操作File对象一样操作Blob对象,实际上,File继承自Blob。

Blob基本用法

创建

可以通过Blob的构造函数创建Blob对象:

Blob(blobParts[, options])

参数说明:

blobParts:数组类型,数组中的每一项连接起来构成Blob对象的数据,数组中的每项元素可以是ArrayBuffer, ArrayBufferView, Blob, DOMString

options:可选项,字典格式类型,可以指定如下两个属性:

  • type,默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型。
  • endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native",表示行结束符会被更改为适合宿主操作系统文件系统的换行符; "transparent",表示会保持blob中保存的结束符不变。

例如:

    var data1 = "a";
var data2 = "b";
var data3 = "<div style='color:red;'>This is a blob</div>";
var data4 = { "name": "abc" }; var blob1 = new Blob([data1]);
var blob2 = new Blob([data1, data2]);
var blob3 = new Blob([data3]);
var blob4 = new Blob([JSON.stringify(data4)]);
var blob5 = new Blob([data4]);
var blob6 = new Blob([data3, data4]); console.log(blob1); //输出:Blob {size: 1, type: ""}
console.log(blob2); //输出:Blob {size: 2, type: ""}
console.log(blob3); //输出:Blob {size: 44, type: ""}
console.log(blob4); //输出:Blob {size: 14, type: ""}
console.log(blob5); //输出:Blob {size: 15, type: ""}
console.log(blob6); //输出:Blob {size: 59, type: ""}

size代表Blob 对象中所包含数据的字节数。这里要注意,使用字符串和普通对象创建Blob时的不同,blob4使用通过JSON.stringify把data4对象转换成json字符串,blob5则直接使用data4创建,两个对象的size分别为14和15。blob4的size等于14很容易理解,因为JSON.stringify(data4)的结果为:"{"name":"abc"}",正好14个字节(不包含最外层的引号)。blob5的size等于15是如何计算而来的呢?实际上,当使用普通对象创建Blob对象时,相当于调用了普通对象的toString()方法得到字符串数据,然后再创建Blob对象。所以,blob5保存的数据是"[object Object]",是15个字节(不包含最外层的引号)。

slice方法

Blob对象有一个slice方法,返回一个新的 Blob对象,包含了源 Blob对象中指定范围内的数据。

slice([start[, end[, contentType]]])

参数说明:

start: 可选,代表 Blob 里的下标,表示第一个会被会被拷贝进新的 Blob 的字节的起始位置。如果传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。

end: 可选,代表的是 Blob 的一个下标,这个下标-1的对应的字节将会是被拷贝进新的Blob 的最后一个字节。如果你传入了一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。

contentType: 可选,给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。

例如:

    var data = "abcdef";
var blob1 = new Blob([data]);
var blob2 = blob1.slice(0,3); console.log(blob1); //输出:Blob {size: 6, type: ""}
console.log(blob2); //输出:Blob {size: 3, type: ""}

通过slice方法,从blob1中创建出一个新的blob对象,size等于3。

Blob使用场景

分片上传

前面已经说过,File继承自Blob,因此我们可以调用slice方法对大文件进行分片长传。代码如下:

function uploadFile(file) {
var chunkSize = 1024 * 1024; // 每片1M大小
var totalSize = file.size;
var chunkQuantity = Math.ceil(totalSize/chunkSize); //分片总数
var offset = 0; // 偏移量 var reader = new FileReader();
reader.onload = function(e) {
var xhr = new XMLHttpRequest();
xhr.open("POST","http://xxxx/upload?fileName="+file.name);
xhr.overrideMimeType("application/octet-stream"); xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
++offset;
if(offset === chunkQuantity) {
alert("上传完成");
} else if(offset === chunkQuantity-1){
blob = file.slice(offset*chunkSize, totalSize); // 上传最后一片
reader.readAsBinaryString(blob);
} else {
blob = file.slice(offset*chunkSize, (offset+1)*chunkSize);
reader.readAsBinaryString(blob);
}
}else {
alert("上传出错");
}
} if(xhr.sendAsBinary) {
xhr.sendAsBinary(e.target.result); // e.target.result是此次读取的分片二进制数据
} else {
xhr.send(e.target.result);
}
}
var blob = file.slice(0, chunkSize);
reader.readAsBinaryString(blob);
}

这段代码还可以进一步丰富,比如显示当前的上传进度,使用多个XMLHttpRequest对象并行上传对象(需要传递分片数据的位置参数给服务器端)等。

Blob URL

Blob URL是blob协议的URL,它的格式如下:

blob:http://XXX

Blob URL可以通过URL.createObjectURL(blob)创建。在绝大部分场景下,我们可以像使用Http协议的URL一样,使用Blob URL。常见的场景有:作为文件的下载地址和作为图片资源地址。

  • 文件下载地址
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Blob Test</title>
<script>
function createDownloadFile() {
var content = "Blob Data";
var blob = new Blob([content]);
var link = document.getElementsByTagName("a")[0];
link.download = "file";
link.href = URL.createObjectURL(blob);
}
window.onload = createDownloadFile;
</script>
</head> <body>
<a>下载</a>
</body> </html>

点击下载按钮,浏览器将会下载一个名为file的文件,文件的内容是:Blob Data。通过Blob对象,我们在前端代码中就可以动态生成文件,提供给浏览器下载。打开Chrome浏览器调试窗口,在Elements标签下可以看到生成的Blob URL为:

  • 图片资源地址

为图片文件创建一个Blob URL,赋值给<img>标签:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Blob Test</title>
<script>
function handleFile(e) {
var file = e.files[0];
var blob = URL.createObjectURL(file);
var img = document.getElementsByTagName("img")[0];
img.src = blob;
img.onload = function(e) {
URL.revokeObjectURL(this.src); // 释放createObjectURL创建的对象##
}
}
</script>
</head> <body>
<input type="file" accept="image/*" onchange="handleFile(this)" />
<br/>
<img style="width:200px;height:200px">
</body> </html>

input中选择的图片会在<img>里显示出来,如图所示:

同时,可以在Network标签栏,发现这个Blob URL的请求信息:

这个请求信息和平时我们使用的Http URL获取图片几乎完全一样。我们还可以使用Data URL加载图片资源:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Blob Test</title>
<script>
function handleFile(e) {
var file = e.files[0];
var fileReader = new FileReader();
var img = document.getElementsByTagName("img")[0];
fileReader.onload = function(e) {
img.src = e.target.result;
}
fileReader.readAsDataURL(file);
}
</script>
</head> <body>
<input type="file" accept="image/*" onchange="handleFile(this)" />
<br/>
<img style="width:200px;height:200px">
</body> </html>

FileReader的readAsDataURL生成一个Data URL,如图所示:

Data URL对大家来说应该并不陌生,Web性能优化中有一项措施:把小图片用base64编码直接嵌入到HTML文件中,实际上就是利用了Data URL来获取嵌入的图片数据。

那么Blob URL和Data URL有什么区别呢?

  1. Blob URL的长度一般比较短,但Data URL因为直接存储图片base64编码后的数据,往往很长,如上图所示,浏览器在显示Data URL时使用了省略号(…)。当显式大图片时,使用Blob URL能获取更好的可能性。
  2. Blob URL可以方便的使用XMLHttpRequest获取源数据,例如:
var blobUrl = URL.createObjectURL(new Blob(['Test'], {type: 'text/plain'}));
var x = new XMLHttpRequest();
// 如果设置x.responseType = 'blob',将返回一个Blob对象,而不是文本:
// x.responseType = 'blob';
x.onload = function() {
alert(x.responseText); // 输出 Test
};
x.open('get', blobUrl);
x.send();

对于Data URL,并不是所有浏览器都支持通过XMLHttpRequest获取源数据的。

3.Blob URL 只能在当前应用内部使用,把Blob URL复制到浏览器的地址栏中,是无法获取数据的。Data URL相比之下,就有很好的移植性,你可以在任意浏览器中使用。

除了可以用作图片资源的网络地址,Blob URL也可以用作其他资源的网络地址,例如html文件、json文件等,为了保证浏览器能正确的解析Blob URL返回的文件类型,需要在创建Blob对象时指定相应的type:

// 创建HTML文件的Blob URL
var data = "<div style='color:red;'>This is a blob</div>";
var blob = new Blob([data], { type: 'text/html' });
var blobURL = URL.createObjectURL(blob); // 创建JSON文件的Blob URL
var data = { "name": "abc" };
var blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
var blobURL = URL.createObjectURL(blob);

欢迎关注我的公众号:老干部的大前端,领取21本大前端精选书籍!

细说Web API中的Blob的更多相关文章

  1. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  2. ASP.NET Web API中的Controller

    虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...

  3. Web APi 2.0优点和特点?在Web APi中如何启动Session状态?

    前言 曾几何时,微软基于Web服务技术给出最流行的基于XML且以扩展名为.asmx结尾的Web Service,此服务在.NET Framework中风靡一时同时也被.NET业界同仁所青睐,几年后在此 ...

  4. 在ASP.NET Web API中使用OData

    http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...

  5. Web Api中的get传值和post传值

    GET 方式 get方式传参 我们一般用于获取数据做条件筛选,也就是 “查” 1.无参 var look = function () { $.ajax({ type: "GET", ...

  6. WEB API 中HTTP的get、post、put,delete 请求方式

    一.WEB API 中HTTP 请求方式的四个主要方法 (GET, PUT, POST, DELETE), 按照下列方式映射为 CURD 操作: 1.POST 用于新建资源,服务端在指定的URI 上创 ...

  7. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【五】——在Web Api中实现Http方法(Put,Post,Delete)

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我们对资源的CRUD操作都是通过相应的Http方法来实现——Post(新 ...

  8. ASP.NET Web API 中的异常处理(转载)

    转载地址:ASP.NET Web API 中的异常处理

  9. Web Api 中Get 和 Post 请求的多种情况分析

    转自:http://www.cnblogs.com/babycool/p/3922738.html 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用J ...

随机推荐

  1. Java课程设计---索引

    一.基础配置 ============================================================== 1.Java课程设计---Eclipse基本环境配置 2.J ...

  2. Go标准的目录结构(自总结)

    微服务版 ├── LICENSE.md ├── Makefile //在任何一个项目中都会存在一些需要运行的脚本,这些脚本文件应该被放到 /scripts 目录中并由 Makefile 触发 ├── ...

  3. sprintf的用法总结

    大概知道sprintf的用法,今天在CSDN上看到一篇关于sprintf比较好的总结,现在抄下来,emmmmmmm....... srpintf()函数的功能非常强大:效率比一些字符串操作函数要高:而 ...

  4. Jmeter--由PV估算tps和最大并发数

    需求 "假设一个系统的业务有登录.浏览帖子.发送新贴.回复帖子,访问高峰是上午10点,日访问高峰PV约5208(含登录1300.浏览2706.发帖526.回帖676).系统响应时间要求小于3 ...

  5. 矩池云上使用nvidia-smi命令教程

    简介 nvidia-smi全称是NVIDIA System Management Interface ,它是一个基于NVIDIA Management Library(NVML)构建的命令行实用工具, ...

  6. Zookeeper(1)-安装与基础使用

    Zookeeper 服务端 工作机制 Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发 ...

  7. 被vector动态扩容给坑了!

    大家好,我是东北码农.记录一下工作中事. 前几天,运维同事给我反馈了一个问题: 通过监控发现,线上的一个服务,业务线程时不时会出现卡顿,卡顿大约持续几秒. 我们做金融系统后台开发的,对性能要求很严格的 ...

  8. Redis环境搭建-Linux单机

    一.准备Linux 可以买云服务器,也可以用虚拟机,我用的是虚拟机Oracle VM VirtualBox 二.编译环境 1.检查linux下是否安装环境 yum list installed | g ...

  9. 面试题--Nginx

    Nginx面试题 整理自网络,侵权删 1.请解释一下什么是Nginx? Nginx是一个web服务器和反向代理服务器,用于http.https.smtp.pop3和IMAP协议 2.请列举Nginx的 ...

  10. linux作业--第一周

    1.按系列罗列Linux的发行版,并描述不同发行版之间的联系与区别. 目前三大主流发行版分别为Debian.Redhat.SUSE. redhat: RHEL: Red Hat公司发布的面向企业用户的 ...