二进制对象:Blob、File和它们的读取对象:FileReader

一、Blob 对象

Blob,全称 Binary Large Object,代表二进制类型的大对象。在Web领域,Blob对象表示一个不可变、二进制原始数据的类文件对象,因此可以像操作文件对象一样操作Blob对象。File 接口基于Blob,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。

一、Blob基本用法

1. 创建Blob对象

生成Blob对象有两种方法:

  1. 使用Blob构造函数(用于从其他非blob对象和数据构造一个 Blob
  2. 对已有的Blob对象使用slice()方法切出一段(用于创建一个 blob 数据的子集 blob)

1)Blob构造函数

var aBlob = new Blob( array[, options] );

Blob() 构造函数返回一个新的 Blob 对象,其内容由参数数组中给出的值串联组成。

参数:

     array:是一个由 ArrayBufferArrayBufferViewBlobDOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。 

     options:配置属性(可选)。可以指定如下两个属性:

             1. type,默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型。'text/csv,charset=UTF-8' 设置为csv格式,并设置编码为UTF-8。

             2. endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持blob中保存的结束符不变。

示例:

var data1 = '我是Blob';
var data2 = "<div style='color:red;'>This is a blob</div>"; // DOMString
var data3 = {hello: "world"};

var blob1 = new Blob([data1], {type: 'text/html'});
var blob2 = new Blob([data2], {type: 'text/html'});
var blob3 = new Blob([data1, data2]);
var blob4 = new Blob([JSON.stringify(data3, null, 2)], {type: 'application/json'});

注意:如果要转成Blob的数据是普通对象,要先用 JSON.stringify() 转换成字符串。

new Blob([{name: 'abc'}])

上述的写法会先调用普通对象的toString()方法得到字符串数据,然后再创建Blob对象。所以,上述保存的数据是"[object Object]"。

Blob属性

blob.size   //Blob大小(以字节为单位)
blob.type   //Blob的MIME类型,如果是未知,则是""(空字符串)

2)slice() 创建

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

参数说明:

  • start 可选,开始索引,可以为负数,语法类似于数组的slice方法.默认值为0.

  • end 可选,结束索引,可以为负数,语法类似于数组的slice方法.默认值为最后一个索引.

  • contentType 可选 ,新的Blob对象的MIME类型,这个值将会成为新的Blob对象的type属性的值,默认为一个空字符串.

2. URL.createObjectURL(blob)

该方法用于生成一个 blob URL 指向Blob 。

var url = URL.createObjectURL(blob);
// 会产生一个类似 blob:d3958f5c-0777-0845-9dcf-2cb28783acaf 这样的URL字符串
// 你可以像使用普通 URL 那样使用它,比如用在 img.src 上。

3. URL.revokeObjectURL(url)

该方法用来释放调用 URL.createObjectURL() 生成的 URL 对象。当你结束使用某个 URL 对象时,应该通过调用这个方法来让浏览器知道不再需要保持这个文件的引用了。

var url = URL.createObjectURL(blob);
URL.revokeObjectURL(url);

二、Blob使用场景

1. Blob URL

文件下载地址:

<a download="data.txt" id="getData">下载</a>
var data= 'Hello world!';  
var blob = new Blob([data], {type: 'text/html,charset=UTF-8'});
window.URL = window.URL || window.webkitURL; 
document.querySelector("#getData").href = URL.createObjectURL(blob);

图片资源地址:

<!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); // 释放
            }
        }
    </script>
</head>
<body>
    <input type="file" accept="image/*" οnchange="handleFile(this)" />
    <br/>
    <img style="width:200px;height:200px">
</body>
</html>

使用 createObjectURL(blob) 输出页面,移动端长按保存,转发

2. 大文件分割上传

主要是利用Blob中 slice() 方法。

function upload(blobOrFile) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/server', true);
  xhr.onload = function(e) { ... };
  xhr.send(blobOrFile);
}

document.querySelector('input[type="file"]').addEventListener('change', function(e) {
  var blob = this.files[0];

  const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.
  const SIZE = blob.size;

  var start = 0;
  var end = BYTES_PER_CHUNK;

  while(start < SIZE) {
    upload(blob.slice(start, end));

    start = end;
    end = start + BYTES_PER_CHUNK;
  }
}, false);
})();

更详细内容

3. 隐藏视频源路径

var video = document.getElementById('video');
var obj_url = window.URL.createObjectURL(blob);
video.src = obj_url;
video.play()
window.URL.revokeObjectURL(obj_url);

三、从 Blob 中提取数据

一种从Blob中读取内容的方法是使用 FileReader。以下代码将 Blob 的内容作为类型数组读取:

var reader = new FileReader();
reader.addEventListener("loadend", function() {
   // reader.result 包含被转化为类型数组 typed array 的 blob
});
reader.readAsArrayBuffer(blob);

另一种读取Blob中内容的方式是使用Response对象。下述代码将Blob中的内容读取为文本:

var text = await (new Response(blob)).text();

二、File 对象

文件(File)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。

通常情况下, File 对象是来自用户在一个 <input> 元素上选择文件后返回的 FileList 对象,也可以是来自由拖放操作生成的 DataTransfer 对象,或者来自 HTMLCanvasElement 上的 mozGetAsFile() API。

File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。比如说, FileReaderURL.createObjectURL()createImageBitmap(), 及 XMLHttpRequest.send() 都能处理 Blob 和 File

构造函数

var myFile = new File(bits, name[, options]);

返回一个新构建的文件对象(File)。

参数:

  • bitsArrayBufferArrayBufferViewBlob,或者 DOMString 对象的 Array — 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。
  • name:USVString,表示文件名称,或者文件路径。
  • options: 可选。配置属性。可用的选项如下:

       type: 表示将要放到文件中的内容的 MIME 类型。默认值为 "" 。

       lastModified: 表示文件最后修改时间的 Unix 时间戳(毫秒)。默认值为 Date.now()

示例:

var file = new File(["foo"], "foo.txt", {
  type: "text/plain",
});

属性

1. File.lastModified 

返回当前 File 对象所引用文件最后修改时间,自 UNIX 时间起始值(1970年1月1日 00:00:00 UTC)以来的毫秒数。

2. File.name 

返回当前 File 对象所引用文件的名字。

3. File.size

返回文件的大小。

4. File.type 

返回文件的 MIME Type。

三、FileReader 对象

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

构造函数

var reader = new FileReader();

示例:

function printFile(file) {
  var reader = new FileReader();
  reader.onload = function(evt) {
    console.log(evt.target.result);
  };
  reader.readAsText(file);
}

属性

1. FileReader.error表示在读取文件时发生的错误 。

2. FileReader.readyState表示FileReader状态的数字。取值如下:

常量名 描述
EMPTY 0 还没有加载任何数据.
LOADING 1 数据正在被加载.
DONE 2 已完成全部的读取请求.

3. FileReader.result文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。

事件处理

以下列了价格主要的事件处理:

1. FileReader.onerror

处理error事件。该事件在读取操作发生错误时触发。

2. FileReader.onload

处理load事件。该事件在读取操作完成时触发。

3. FileReader.onloadend

处理loadend事件。该事件在读取操作结束时(要么成功,要么失败)触发。

4. FileReader.onprogress

处理progress事件。该事件在读取Blob时触发。

方法

1. FileReader.abort()

中止读取操作。在返回时,readyState属性为DONE

注意:对一个没有正在进行读取操作(readyState 不是LOADING)的 FileReader 进行 abort 操作,会抛出 DOM_FILE_ABORT_ERR 错误。

2. FileReader.readAsArrayBuffer(blob)

用于启动读取指定的 Blob 或 File 内容。当读取操作完成时,readyState 变成 DONE(已完成),并触发 loadend 事件,同时 result 属性中将包含一个 ArrayBuffer 对象以表示所读取文件的数据。

3. FileReader.readAsDataURL(blob)

读取指定的 Blob 或 File 对象。读取操作完成的时候, result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
4. FileReader.readAsText()

将 Blob 或者 File 对象转成指定编码格式的文本字符串。

FileReader.readAsText(blob[, encoding])

encoding:编码类型,默认为“utf-8”类型。

示例

示例1:使用 readAsDataURL()

<input type="file" οnchange="previewFile()"><br>
<img src="" height="200" alt="Image preview...">
function previewFile() {
  var preview = document.querySelector('img');
  var file    = document.querySelector('input[type=file]').files[0];
  var reader  = new FileReader();

  reader.addEventListener("load", function () {
    preview.src = reader.result;
  }, false);

  if (file) {
    reader.readAsDataURL(file);
  }
}

// 也可以写成如下形式
function previewFile() {
  var preview = document.querySelector('img');
  var file    = document.querySelector('input[type=file]').files[0];
  var reader  = new FileReader();

  // 就这里不一样
  reader.onload = function (e) {
    preview.src = e.target.result;
  };

  if (file) {
    reader.readAsDataURL(file);
  }
}

四、Data URL

即前缀为 data: 协议的的URL,其允许内容创建者向文档中嵌入小文件。

Data URL 由四个部分组成:

  • 前缀(data:)
  • 指示数据类型的MIME类型
  • 如果非文本则为可选的base64标记
  • 数据本身
data:[<mediatype>][;base64],<data>

mediatype 是个 MIME 类型的字符串,例如 "image/jpeg" 表示 JPEG 图像文件。如果被省略,则默认值为 text/plain;charset=US-ASCII。

如果数据是文本类型,你可以直接将文本嵌入 (根据文档类型,使用合适的实体字符或转义字符)。如果是二进制数据,你可以将数据进行base64编码之后再进行嵌入。

示例:

//简单的 text/plain 类型数据
data:,Hello%2C%20World!
//上一条示例的 base64 编码版本
data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
//一个HTML文档源代码 <h1>Hello, World</h1>
data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
//一个会执行 JavaScript alert 的 HTML 文档。
data:text/html,<script>alert('hi');</script>

生成 DataURL 用 FileReaderreadAsDataURL(blob) 方法。

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);


 

 

参考文章

 

发布了122 篇原创文章 · 获赞 87 · 访问量 52万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章