JSON中保存Blob对象的实用指南
在Web开发中,Blob(Binary Large Object)常用于处理二进制数据,如图片、音频、视频或文件等,而JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,通常用于结构化文本数据的存储和传输,如何将Blob对象保存到JSON中呢?本文将详细介绍Blob对象的特点、JSON的限制,以及三种常见的Blob保存与读取方法。
Blob对象与JSON的“冲突”:为什么不能直接保存?
Blob是JavaScript中表示二进制数据的对象,本质上是不可变的原始数据块,包含不可直接编辑的原始字节,而JSON的核心是文本格式,仅支持以下数据类型:字符串、数字、布尔值、null、数组以及对象(键值对集合)。Blob对象无法直接序列化为JSON,因为JSON无法原生表示二进制数据——就像你不能直接把一张图片“写”进一个纯文本文件一样。
举个简单的例子,直接尝试将Blob对象存入JSON会得到[object Blob]这样的无效结果:
const blob = new Blob(["Hello, Blob!"], { type: "text/plain" });
const data = { message: blob, id: 1 };
const jsonStr = JSON.stringify(data); // 输出: '{"message":"[object Blob]","id":1}'
// 此时jsonStr中的blob已丢失原始二进制数据
核心思路:将Blob转换为可JSON化的格式
既然Blob不能直接存入JSON,我们需要通过“中间转换”将其转换为JSON支持的格式,常见的转换思路有两种:
- Base64编码:将二进制数据转换为Base64字符串(ASCII字符),可直接存入JSON。
- ArrayBuffer+类型信息:将Blob转换为ArrayBuffer(二进制数据缓冲区),结合MIME类型(如
"image/png")保存为JSON对象。
三种Blob保存与读取方法
方法1:Base64编码(适合小文件)
Base64是一种将二进制数据转换为64个可打印字符的编码方式,可直接嵌入JSON字符串中。
保存Blob到JSON
- 将Blob转换为ArrayBuffer(二进制数据)。
- 将ArrayBuffer转换为Base64字符串。
- 将Base64字符串存入JSON,并保留MIME类型(用于后续解析)。
// 1. 创建Blob(示例:文本文件)
const blob = new Blob(["Hello, JSON + Blob!"], { type: "text/plain" });
// 2. 转换为Base64字符串
const reader = new FileReader();
reader.onload = function(event) {
const base64 = event.target.result.split(',')[1]; // 去掉"data:;base64,"前缀
// 3. 存入JSON
const data = {
id: 1,
name: "sample.txt",
type: blob.type, // 保留MIME类型
content: base64 // Base64字符串
};
const jsonStr = JSON.stringify(data);
console.log("JSON with Base64 Blob:", jsonStr);
};
reader.readAsDataURL(blob); // readAsDataURL会返回Base64编码的Data URL
从JSON读取并恢复Blob
- 解析JSON,提取Base64字符串和MIME类型。
- 将Base64字符串转换为ArrayBuffer(或直接使用Data URL)。
- 通过ArrayBuffer或Data URL重建Blob对象。
// 假设从JSON解析出的数据
const jsonData = {
id: 1,
name: "sample.txt",
type: "text/plain",
content: "SGVsbG8sIEpTT04gKyBCbG9iIQ==" // Base64编码的"Hello, JSON + Blob!"
};
// 1. 解析Base64字符串
const base64Data = jsonData.content;
const mimeType = jsonData.type;
const byteCharacters = atob(base64Data); // atob()解码Base64
const byteArrays = [];
// 2. 将Base64转换为ArrayBuffer
for (let i = 0; i < byteCharacters.length; i++) {
byteArrays.push(byteCharacters.charCodeAt(i));
}
const byteArray = new Uint8Array(byteArrays);
const blob = new Blob([byteArray], { type: mimeType });
// 3. 验证Blob内容
const reader = new FileReader();
reader.onload = function(event) {
console.log("恢复的Blob内容:", event.target.result); // 输出: "Hello, JSON + Blob!"
};
reader.readAsText(blob);
方法2:ArrayBuffer + 类型信息(适合大文件)
Base64编码会使数据体积增加约33%(每3个字节变成4个字符),对于大文件(如视频)可能影响性能,此时可采用ArrayBuffer(二进制缓冲区)+ 类型信息的方式,但需注意:ArrayBuffer本身不能直接JSON化,需先转换为Base64或使用TextEncoder(仅适合文本)。
保存Blob到JSON(ArrayBuffer + Base64)
const blob = new Blob(["Large binary data..."], { type: "application/octet-stream" });
const reader = new FileReader();
reader.onload = function(event) {
const arrayBuffer = event.target.result;
// 将ArrayBuffer转换为Base64(同方法1)
const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
const data = {
id: 2,
type: blob.type,
buffer: base64 // 存储ArrayBuffer的Base64编码
};
const jsonStr = JSON.stringify(data);
console.log("JSON with ArrayBuffer (Base64):", jsonStr);
};
reader.readAsArrayBuffer(blob); // 读取为ArrayBuffer
从JSON读取并恢复Blob
const jsonData = {
id: 2,
type: "application/octet-stream",
buffer: "TGFyZ2UgYmluYXJ5IGRhdGEuLi4=" // Base64编码的"Large binary data..."
};
// 解码Base64并重建ArrayBuffer
const base64Data = jsonData.buffer;
const byteCharacters = atob(base64Data);
const byteArrays = new Uint8Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteArrays[i] = byteCharacters.charCodeAt(i);
}
const blob = new Blob([byteArrays], { type: jsonData.type });
console.log("恢复的Blob类型:", blob.type); // 输出: "application/octet-stream"
方法3:引用外部存储(适合超大文件)
如果Blob体积极大(如GB级视频),直接编码到JSON会导致字符串过长,影响存储和传输效率,此时可采用“JSON存储引用,二进制数据单独存储”的方式:
保存Blob到JSON(引用外部URL)
- 将Blob上传到服务器(或本地存储),获取访问URL(如
/uploads/file123.bin)。 - 在JSON中存储URL和元数据(如文件名、类型、大小)。
// 模拟上传Blob到服务器(实际开发中用fetch或axios)
async function uploadBlob(blob) {
// 假设返回上传后的URL
const url = `/uploads/${Date.now()}-${blob.name || 'file'}`;
// 实际开发中:const response = await fetch(url, { method: 'PUT', body: blob });
return url;
}
const blob = new Blob(["Huge video data..."], { type: "video/mp4", name: "video.mp4" });
uploadBlob(blob).then(url => {
const data = {
id: 3,
name: blob.name,
type: blob.type,
size: blob.size,
url: url // JSON中只存URL
};
const jsonStr = JSON.stringify(data);
console.log("JSON with external URL:", jsonStr);
});
从JSON读取并获取Blob
const jsonData = {
id: 3,
name: "video.mp4",
type: "video/mp4",
size: 1024000,
url: "/uploads/1234567890-video.mp4"
};
// 通过URL获取Blob(实际开发中用fetch)
fetch(jsonData.url)
.then(response => response.blob())
.then(blob => {
console.log("获取的Blob:", blob);
console.log("Blob类型:", blob.type); // 输出: "video/mp4"
});
方法对比与选择建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Base64编码 | 实现简单,数据内嵌,无需额外存储 | 体积增加33%,大文件性能低 | 小文件(如图片、文本) |
| ArrayBuffer + Base64 | 二进制数据更直接,适合非文本 | 仍需Base64编码,体积增加 | 二进制小文件(如音频、PDF) |
| 外部URL引用 | JSON体积小,适合超大文件 | 依赖外部存储,需额外处理网络请求 | 超大文件(如视频、大型数据集) |



还没有评论,来说两句吧...