一、核心概念与关系
ArrayBuffer ──────────────────────────────────────────────────
│ 原始二进制内存,不能直接读写 │
▼ │
TypedArray / DataView ← 视图层,用于读写 ArrayBuffer │
(Uint8Array, Int32Array, Float64Array…) │
│
Blob ───── 不可变的二进制大对象,有 type(MIME) │
│ │
▼ (继承) │
File ───── 在 Blob 基础上增加 name / lastModified │
│
互转链路: │
ArrayBuffer ──► Uint8Array ──► Blob ──► File │
File / Blob ──► ArrayBuffer (通过 .arrayBuffer() 或 FileReader)
二、各类型速查
| 类型 | 可变? | 直接读写? | 用途 |
|---|
ArrayBuffer | 否(需视图) | ❌ | 原始内存容器 |
TypedArray | ✅ | ✅ | 数值型数组操作 |
DataView | ✅ | ✅ | 精确控制字节序(endian) |
Blob | ❌ | ❌ | 文件内容、网络传输 |
File | ❌ | ❌ | 用户上传文件 |
三、ArrayBuffer 操作
3.1 创建
const buf = new ArrayBuffer(16);
3.2 通过 TypedArray 读写
const view = new Uint8Array(buf)
view[0] = 255
view[1] = 128
const int32 = new Int32Array(buf)
int32[0] = 42
const float64 = new Float64Array(buf)
float64[0] = 3.14
3.3 通过 DataView 控制字节序
const dv = new DataView(buf);
dv.setInt32(0, 300, true);
dv.getInt32(0, true);
dv.setFloat32(4, 1.5, false);
dv.getFloat32(4, false);
3.4 切片(复制新 buffer)
const sliced = buf.slice(0, 8)
3.5 复制 / 合并
function concat(...buffers) {
const total = buffers.reduce((n, b) => n + b.byteLength, 0);
const result = new Uint8Array(total);
let offset = 0;
for (const b of buffers) {
result.set(new Uint8Array(b), offset);
offset += b.byteLength;
}
return result.buffer;
}
3.6 转字符串
// ArrayBuffer → UTF-8 字符串
const decoder = new TextDecoder('utf-8')
const str = decoder.decode(buf)
// 字符串 → ArrayBuffer
const encoder = new TextEncoder()
const buf2 = encoder.encode('Hello').buffer
四、互转方法
4.1 ArrayBuffer → Blob
const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' });
4.2 Blob → ArrayBuffer
// 现代方式(推荐)
const buf = await blob.arrayBuffer()
// 旧方式(兼容性)
function blobToBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = () => resolve(reader.result)
reader.onerror = reject
reader.readAsArrayBuffer(blob)
})
}
4.3 Blob → File
const file = new File([blob], 'example.png', {
type: 'image/png',
lastModified: Date.now(),
});
4.4 File → ArrayBuffer
const buf = await file.arrayBuffer();
4.5 ArrayBuffer → Base64
const base64 = btoa(
String.fromCharCode(...new Uint8Array(arrayBuffer))
);
const bin = atob(base64);
const buf = new Uint8Array(bin.length).map((_, i) => bin.charCodeAt(i)).buffer;
4.6 Blob → Object URL(预览/下载)
const url = URL.createObjectURL(blob)
// 用完释放
URL.revokeObjectURL(url)
4.7 Blob → 文本
const text = await blob.text();
const json = JSON.parse(await blob.text());
五、常用场景示例
5.1 读取用户上传文件
input.addEventListener('change', async (e) => {
const file = e.target.files[0]
const buffer = await file.arrayBuffer()
const view = new Uint8Array(buffer)
console.log(view[0], view[1])
})
5.2 下载二进制数据
const response = await fetch('/api/file')
const buffer = await response.arrayBuffer()
const blob = new Blob([buffer], { type: 'application/pdf' })
const a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = 'result.pdf'
a.click()
URL.revokeObjectURL(a.href)
5.3 修改图片二进制头(示例:读 PNG 宽高)
const buf = await file.arrayBuffer()
const dv = new DataView(buf)
// PNG: 宽在偏移 16,高在偏移 20(大端)
const width = dv.getUint32(16, false)
const height = dv.getUint32(20, false)
5.4 WebSocket 发送 / 接收二进制
ws.binaryType = 'arraybuffer'
ws.onmessage = (e) => {
const view = new Uint8Array(e.data)
}
// 发送
ws.send(new Uint8Array([0x01, 0x02, 0x03]).buffer)
5.5 上传 Blob / File(FormData)
const form = new FormData();
form.append('file', file);
form.append('file', blob, 'data.bin');
await fetch('/upload', { method: 'POST', body: form });
六、关系总图(文字版)
用户选文件
│
▼
File (name, lastModified, type)
│ 继承
▼
Blob (不可变, type)
│
├─ .arrayBuffer() ──► ArrayBuffer ──► TypedArray / DataView (读写字节)
├─ .text() ──► string
├─ .stream() ──► ReadableStream
└─ URL.createObjectURL() ──► blob:
ArrayBuffer
├─ new Blob([buf]) ──► Blob
├─ new Uint8Array(buf) ──► TypedArray(视图)
├─ new DataView(buf) ──► DataView(视图)
└─ TextDecoder.decode(buf) ──► string
七、兼容性提示
| API | 兼容性 |
|---|
blob.arrayBuffer() | Chrome 76+, Firefox 69+, Node 15+ |
blob.text() | 同上 |
FileReader | 全浏览器,旧项目兼容方案 |
TextEncoder/Decoder | 现代浏览器 & Node 11+ |
ArrayBuffer.transfer() | Chrome 114+(零拷贝转移所有权) |