ArrayBuffer / TypedArray / Blob / File 关系与操作指南


一、核心概念与关系

javascript 复制代码
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 创建

javascript 复制代码
const buf = new ArrayBuffer(16); // 分配 16 字节,全为 0

3.2 通过 TypedArray 读写

ini 复制代码
const view = new Uint8Array(buf);
view[0] = 255;
view[1] = 128;

const int32 = new Int32Array(buf);
int32[0] = 42; // 占 4 字节

const float64 = new Float64Array(buf);
float64[0] = 3.14; // 占 8 字节

3.3 通过 DataView 控制字节序

javascript 复制代码
const dv = new DataView(buf);

dv.setInt32(0, 300, true);   // true = 小端(little-endian)
dv.getInt32(0, true);        // 读取 → 300

dv.setFloat32(4, 1.5, false); // false = 大端(big-endian)
dv.getFloat32(4, false);      // → 1.5

3.4 切片(复制新 buffer)

ini 复制代码
const sliced = buf.slice(0, 8); // 取前 8 字节,返回新 ArrayBuffer

3.5 复制 / 合并

javascript 复制代码
// 合并多个 ArrayBuffer
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 转字符串

ini 复制代码
// 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

go 复制代码
const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' });

4.2 Blob → ArrayBuffer

ini 复制代码
// 现代方式(推荐)
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

go 复制代码
const file = new File([blob], 'example.png', {
  type: 'image/png',
  lastModified: Date.now(),
});

4.4 File → ArrayBuffer

csharp 复制代码
const buf = await file.arrayBuffer(); // File 继承自 Blob

4.5 ArrayBuffer → Base64

javascript 复制代码
const base64 = btoa(
  String.fromCharCode(...new Uint8Array(arrayBuffer))
);

// Base64 → ArrayBuffer
const bin = atob(base64);
const buf = new Uint8Array(bin.length).map((_, i) => bin.charCodeAt(i)).buffer;

4.6 Blob → Object URL(预览/下载)

ini 复制代码
const url = URL.createObjectURL(blob);
// 用完释放
URL.revokeObjectURL(url);

4.7 Blob → 文本

vbnet 复制代码
const text = await blob.text();
const json = JSON.parse(await blob.text());

五、常用场景示例

5.1 读取用户上传文件

ini 复制代码
input.addEventListener('change', async (e) => {
  const file = e.target.files[0];          // File 对象
  const buffer = await file.arrayBuffer(); // → ArrayBuffer
  const view   = new Uint8Array(buffer);
  console.log(view[0], view[1]); // 读取头两字节
});

5.2 下载二进制数据

ini 复制代码
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 宽高)

ini 复制代码
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 发送 / 接收二进制

ini 复制代码
ws.binaryType = 'arraybuffer';
ws.onmessage = (e) => {
  const view = new Uint8Array(e.data); // 直接是 ArrayBuffer
};

// 发送
ws.send(new Uint8Array([0x01, 0x02, 0x03]).buffer);

5.5 上传 Blob / File(FormData)

go 复制代码
const form = new FormData();
form.append('file', file);             // File 对象
// 或用 Blob + 指定文件名
form.append('file', blob, 'data.bin');

await fetch('/upload', { method: 'POST', body: form });

六、关系总图(文字版)

typescript 复制代码
用户选文件
    │
    ▼
  File  (name, lastModified, type)
    │   继承
    ▼
  Blob  (不可变, type)
    │
    ├─ .arrayBuffer()  ──►  ArrayBuffer  ──►  TypedArray / DataView  (读写字节)
    ├─ .text()         ──►  string
    ├─ .stream()       ──►  ReadableStream
    └─ URL.createObjectURL()  ──►  blob:// URL  ──►  <img src> / <a download>

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+(零拷贝转移所有权)
相关推荐
We་ct2 小时前
React 更新触发原理详解
开发语言·前端·javascript·react.js·面试·前端框架·react
还是大剑师兰特2 小时前
Vue3 页面权限控制实战示例(路由守卫 + 权限判断)
开发语言·前端·javascript
冉冉同学2 小时前
Vibe Coding指南【道、法、术】
前端·人工智能·后端
枕布响丸辣2 小时前
Web 技术基础与 Nginx 网站环境部署超详细教程
运维·前端·nginx
又是忙碌的一天2 小时前
Java 面向对象三大特性:封装、继承、多态深度解析
java·前端·python
跟着珅聪学java2 小时前
Vue 2 + CommonJS 写法开发教程
前端·javascript·vue.js
minstbe2 小时前
IC设计私有化AI助手实战:基于Docker+OpenCode+Ollama的数字前端综合增强方案(基础版)
前端·人工智能·docker