[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 规格,并且增加了新的方法。它们都以数组的语法处理二进制数据,所以统称为**二进制数组**。
 为什么要以二进制而不是传统的文本格式来进行数据通信?文本格式传递数据是比较费时的(格式转换),这个接口的原始设计目的与 WebGL 项目有关,WebGL 即浏览器与显卡之间的通信接口,为了满足 JavaScript 与显卡之间大量、实时的数据交换,它们之间的数据通信必须是二进制的。
 二进制数组允许开发者以数组下标的形式直接操作内存,大大增强了 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/)
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直线、矩形、多边形
- Part2-曲线图形
- Part3-线条操作
- Part4-文本操作
- Part5-图像操作
- Part6-变形操作
- Part7-像素操作
- Part8-渐变与阴影
- Part9-路径与状态
- Part10-物理动画
- Part11-边界检测
- Part12-碰撞检测
- Part13-用户交互
- Part14-高级动画
- CSS
- SCSS
- codePen
- 速查表
- 面试题
- 《CSS Secrets》
- SVG
- 移动端适配
- 滤镜(filter)的使用
- JS
- 基础概念
- 作用域、作用域链、闭包
- this
- 原型与继承
- 数组、字符串、Map、Set方法整理
- 垃圾回收机制
- DOM
- BOM
- 事件循环
- 严格模式
- 正则表达式
- ES6部分
- 设计模式
- AJAX
- 模块化
- 读冴羽博客笔记
- 第一部分总结-深入JS系列
- 第二部分总结-专题系列
- 第三部分总结-ES6系列
- 网络请求中的数据类型
- 事件
- 表单
- 函数式编程
- Tips
- JS-Coding
- Framework
- Vue
- 书写规范
- 基础
- vue-router & vuex
- 深入浅出 Vue
- 响应式原理及其他
- new Vue 发生了什么
- 组件化
- 编译流程
- Vue Router
- Vuex
- 前端路由的简单实现
- React
- 基础
- 书写规范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 与 Hook
- 《深入浅出React和Redux》笔记
- 前半部分
- 后半部分
- react-transition-group
- Vue 与 React 的对比
- 工程化与架构
- Hybird
- React Native
- 新手上路
- 内置组件
- 常用插件
- 问题记录
- Echarts
- 基础
- Electron
- 序言
- 配置 Electron 开发环境 & 基础概念
- React + TypeScript 仿 Antd
- TypeScript 基础
- 样式设计
- 组件测试
- 图标解决方案
- Algorithm
- 排序算法及常见问题
- 剑指 offer
- 动态规划
- DataStruct
- 概述
- 树
- 链表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 课程实战记录
- 服务器
- 操作系统基础知识
- Linux
- Nginx
- redis
- node.js
- 基础及原生模块
- express框架
- node.js操作数据库
- 《深入浅出 node.js》笔记
- 前半部分
- 后半部分
- 数据库
- SQL
- 面试题收集
- 智力题
- 面试题精选1
- 面试题精选2
- 问答篇
- Other
- markdown 书写
- Git
- LaTex 常用命令