🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] >[info]文件、图片以什么样的形式传输、存储在某些场合是一个很棘手的问题,这里记录一些常用的数据类型 / 形式方便以后查阅 # Blob Blob(binary large object),二进制类文件大对象,是一个可以存储二进制文件的“容器”,HTML5 中的 Blob 对象除了存放二进制数据外还可以设置这个数据的 MIME 类型。File 接口基于 Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。 Blob 构造函数接受两个参数,第一个参数是一个包含实际数据的数组,第二个参数是数据的 MIME 类型(标识邮件和 http 请求的网络数据格式)。 ``` var blob=new Blob([data],{"type":"text/html"}); ``` - Blob.size:放回 blob 对象的数据大小 - Blob.type:返回 blob 对象的 MIME 类型 - Blob.slice():截取指定范围的数据,形成新的 blob 对象 示例1:图片选择与下载 ``` <input type="file" value="点我" id="inputImg" onchange="changeHandle(this)"> <img id="image"> let changeHandle = (file) =>{ var reader = new FileReader(); reader.onload = function(evt){ document.getElementById('image').src = evt.target.result; image = evt.target.result; } // 读Blob为base64 reader.readAsDataURL(file.files[0]); } ``` 示例2:向服务器请求图片并挂载 ``` var xhr = new XMLHttpRequest(); xhr.open("get", "mm1.jpg", true); // 向服务器请求图片 xhr.responseType = "blob"; // blob 形式 xhr.onload = function() { if (this.status == 200) { var blob = this.response; // this.response也就是请求的返回就是Blob对象 var img = document.createElement("img"); img.onload = function(e) { window.URL.revokeObjectURL(img.src); // 清除释放 }; img.src = window.URL.createObjectURL(blob); // 使用该 API 可以创建一个 URL 来访问该图片 eleAppend.appendChild(img); } } xhr.send(); ``` 注意 window.URL.createObjectURL() 这个 API,其可以接收 File 对象或 Blob 对象参数生成一个下载 / 加载链接(???) ``` axios.get('https://xxxxxx', {responseType: 'blob'}) .then(res => { let url = URL.createObjectURL(res.data) let a = document.createElement('a') a.setAttribute('download', '图片') a.href = url a.click() }) ``` ## ArrayBuffer 与 Blob * Blob 和 ArrayBuffer 都能存储二进制数据。Blob 相对而言储存的二进制数据大(如File文件对象)。 * ArrayBuffer 对象表示原始的二进制数据缓冲区,即在内存中分配指定大小的二进制缓冲区(容器),用于存储各种类型化数组的数据,是最基础的原始数据容器,无法直接读取或写入, 需要通过具体视图来读取或写入,即 TypedArray 对象或 DataView 对象对内存大小进行读取或写入;Blob 对象表示一个不可变、原始数据的类文件对象。 可以相互转换。 Blob => ArrayBuffer ``` let blob = new Blob([1,2,3,4]) let reader = new FileReader(); reader.onload = function(result) { console.log(result); } reader.readAsArrayBuffer(blob); ``` ArrayBuffer => Blob ``` let blob = new Blob([buffer]) ``` # 图片格式 - 无压缩。无压缩的图片格式不对图片数据进行压缩处理,能准确地呈现原图片。BMP 格式就是其中之一。 - 无损压缩。压缩算法对图片的所有的数据进行编码压缩,能在保证图片的质量的同时降低图片的尺寸。png 是其中的代表。 - 有损压缩。压缩算法不会对图片所有的数据进行编码压缩,而是在压缩的时候,去除了人眼无法识别的图片细节。因此有损压缩可以在同等图片质量的情况下大幅降低图片的尺寸。其中的代表是 jpg。 |格式 |优点 | 缺点 | 适用场景 | | :----| :----| :----| :----| |gif |文件小,支持动画、透明,无兼容性问题 |只支持 256 种颜色 | 色彩简单的 logo、icon、动图| | jpg(jpeg)| 色彩丰富,文件小|有损压缩,反复保存图片质量下降明显 |色彩丰富的图片/渐变图像 | | png| 无损压缩,支持透明,简单图片尺寸小| 不支持动画,色彩丰富的图片| logo/icon/透明图| |webp | 文件小,支持有损和无损压缩,支持动画、透明|浏览器兼容性不好 | 支持 webp 格式的 app 和 webview| 如何做选择?(Google 图片格式选择指南) ![](https://img.kancloud.cn/35/f4/35f4295961ef264cb3f748f6200f2d5c_605x347.png) # 二进制数组 ArrayBuffer 对象、TypedArray 视图和 DataView 视图是 JavaScript 操作二进制数据的一个接口,ES6 将它们纳入了 ECMAScript 规格,并且增加了新的方法。它们都以数组的语法处理二进制数据,所以统称为**二进制数组**。 &emsp;为什么要以二进制而不是传统的文本格式来进行数据通信?文本格式传递数据是比较费时的(格式转换),这个接口的原始设计目的与 WebGL 项目有关,WebGL 即浏览器与显卡之间的通信接口,为了满足 JavaScript 与显卡之间大量、实时的数据交换,它们之间的数据通信必须是二进制的。 &emsp;二进制数组允许开发者以数组下标的形式直接操作内存,大大增强了 JavaScript 处理二进制数据的能力,其由 3 类对象组成 1. ArrayBuffer 对象:代表内存中的一段二进制数据,可以通过"视图"进行操作。"视图"部署了数组接口,这意味着,可以通过数组的方法操作内存 2. TypedArray 视图:共包括 9 种类型的视图,如 Int16Array(16位整数)数组视图、Float32Array(32位浮点数)数组视图等 3. DataView 视图:可以自定义复合格式的视图,比如第一个字节是 Uint8(无符号8位整数)、第二和第三个字节是 Int16(16位整数) 简而言之:ArrayBuffer 对象代表原始的二进制数据,TypedArray 视图用于读 / 写简单类型的二进制数据,DataView 视图用于读 / 写复杂类型的二进制数据。 > 二进制数组并不是真正的数组,而是类似数组的对象。很多浏览器操作的 API 都用到了二进制数组操作二进制数据,如 File API、XMLHttpRequest、Fetch API、Canvas、WebSocket ## ArrayBuffer 对象 ArrayBuffer 对象代表储存二进制数据的一段内存,它不能直接读 / 写,只能通过视图(TypedArray 视图和 DataView 视图)读 / 写,视图的作用是以指定格式解读二进制数据 - ArrayBuffer():构造函数,分配一段可以存放数据的连续内存区域,单位为字节 ``` var buf = new ArrayBuffer(32) // 生成一段 32 字节的内存区域,每个字节的值默认为 0 ``` - ArrayBuffer.prototype.byteLength:返回所分配的内存区域的字节长度 ``` var buffer = new ArrayBuffer(32) buffer.byteLength // 32 ``` - ArrayBuffer.prototype.slice():将内存区域的一部分复制生成一个新的 ArrayBuffer 对象;slice 方法包含两步:第一步先分配一段新内存,第二步将要复制的内存区域拷贝(是否正确?) ``` var buffer = new ArrayBuffer(8) var newBuffer = buffer.slice(0, 3) // 复制 buffer 对象的前 3 个字节(0, 1, 2) ``` - ArrayBuffer.isView():该方法返回一个布尔值,表示参数是否为 ArrayBuffer 的视图实例 ``` var buffer = new ArrayBuffer(8) ArrayBuffer.isView(buffer) // false var v = new Int32Array(buffer) ArrayBuffer.isView(v) // true ``` ## TypedArray 视图 TypedArray 视图与 DataView 视图的区别是,前者的数组成员都是同一类型,后者的数组成员可以是不同的数据类型。 TypedArray 的每一种视图都是一种构造函数 - Int8Array:8位有符号整数,长度为 1 字节 - Uint8Array:8位无符号整数,长度为 1 个字节 - Uint8ClampedArray:8位无符号整数,长度为 1 个字节,溢出处理不同 - Int16Array:16 位有符号整数,长度为 2 个字节 - Uint16Array:16 位无符号整数 - Int32Array:32 位有符号整数 - Uint32Array:32 位无符号整数 - Float32Array:32 位浮点数,长度为 4 个字节 - Float64Array:64 位浮点数,长度为 8 个字节 这 9 个构造函数生成的数组,统称为 TypedArray 视图,它们很像普通数组,都有 length 属性,都能用方括号运算符([])获取单个元素,所有数组方法都能在其上使用,普通数组与视图数组的差别主要为以下几个方面: - TypedArray 数组的所有成员都是同一种类型 - TypedArray 数组的成员是连续的,不会有空位 - TypedArray 数组成员的默认值为 0 - TypedArray 数组只是一层视图,本身不存储数据,它的数据都存储在底层的 ArrayBuffer 对象中 ``` // 创建一个 8 字节的 ArrayBuffer var b = new ArrayBuffer(8) // 创建一个指向 b 的 Int32 视图,开始于字节 0,直到缓冲区的末尾 var v1 = new Int32Array(b) // 创建一个指向 b 的 Uint8 视图,开始于字节 2,直到缓冲区的末尾 var v2 = new Uint8Array(b, 2) // 创建一个指向 b 的 Int16 视图,开始于字节 2,长度为2 var v3 = new Int16Array(b, 2, 2) ``` 即视图的构造函数可以接受 3 个参数: - 第一个参数(必选):视图对应的 ArrayBuffer 对象 - 第二个参数(可选):视图开始的字节序号,默认从 0 开始 - 第三个参数(可选):视图包含的数据个数,默认直到本段内存区域结束 ## DataView 视图 暂不整理...... ## 二进制数组的应用 ### AJAX 传统上,服务器通过 AJAX 操作只能返回文本数据,即 responseType 属性默认为 text,XHR2 允许服务器返回二进制数据,这时分两种情况:如果明确知道返回的二进制数据类型,可以把返回类型(responseType)设置为 arraybuffer;如果不知道,就设置为 blob ``` var xhr = new XMLHttpRequest() xhr.open('GET', someUrl) xhr.responseType = 'arraybuffer' xhr.onload = function () { // 接收到完整的响应数据时触发 let arrayBuffer = xhr.response // ... } xhr.send() // 如果知道传回来的是 32 位整数,可以像下面这样处理 xhr.onreadystatechange = function () { if (req.readyState === 4) { var arrayResponse = xhr.response var dataView = new DataView(arrayResponse) var ints = new Uint32Array(dataView.byteLength / 4) xhrDiv.innerText = `Array is ${ints.length} uints long` } } ``` ### WebSocket WebSocket 可以通过 ArrayBuffer 发送或接收二进制数据 ### Fetch API ### File API ### SharedArrayBuffer # 参考链接 [https://juejin.im/post/5b32ea55e51d4558bf7c45e0](https://juejin.im/post/5b32ea55e51d4558bf7c45e0) [https://www.zhangxinxu.com/wordpress/2013/10/understand-domstring-document-formdata-blob-file-arraybuffer/](https://www.zhangxinxu.com/wordpress/2013/10/understand-domstring-document-formdata-blob-file-arraybuffer/)