filereader.readasdataurl() 是浏览器中将 blob 转为 base64 的唯一可靠方案,本质是异步读取并封装,需手动截取 data:*,base64, 前缀获取纯 base64 字符串,大文件需防内存压力与中断。

FileReader.readAsDataURL() 是唯一靠谱的方案
浏览器环境里把 Blob 转成 Base64,别想绕开 FileReader——没有同步 API,也没有更短的捷径。它本质是异步读取二进制内容再拼前缀,不是“编码”,而是“读取并封装”。
常见错误现象:atob() 或 btoa() 直接扔 Blob 会报 InvalidCharacterError;用 TextDecoder 读原始字节再 base64 编码,结果乱码——因为没处理二进制边界,且 JS 没内置二进制到 Base64 的同步转换函数。
-
readAsDataURL()自动加data:[type];base64,前缀,拿到的就是完整可用的 Data URL - 如果只需要纯 Base64 字符串(不含前缀),得手动切掉
data:*,base64,这一段 - 大文件(比如 >100MB)可能触发内存压力或卡顿,
FileReader本身不支持进度回调,别指望边读边显示百分比
为什么不能用 fetch + arrayBuffer + btoa 组合
有人试过 fetch(blobUrl).then(r => r.arrayBuffer()) 再转,理论上可行,但实际踩坑密集:Blob URL 生命周期短、跨域限制、btoa() 只接受 Latin-1 字符串,而 arrayBuffer 转字符串时若用 String.fromCharCode(...new Uint8Array(buf)) 会崩在非 ASCII 字节上(比如中文、图片像素值)。
- 正确做法是用
Uint8Array配合自定义 base64 查表函数,但没必要——FileReader已经帮你做了这事 -
fetch方案还多一次 URL 构建和网络栈调度,哪怕本地 blob URL 也走 round-trip,纯属增加不可靠环节 - 兼容性上,
FileReader在 IE10+、所有现代浏览器都稳;fetch+arrayBuffer在 Safari 10.1 之前不支持blob.arrayBuffer()
小文件直接转,大文件得防阻塞
Base64 编码会让体积膨胀约 33%,加上 FileReader 把整个 Blob 加载进内存,100MB 的 Blob 最终可能占 130MB+ 内存。用户切屏或切换标签页时,Chrome 可能直接终止读取并触发 onerror。
立即学习“前端免费学习笔记(深入)”;
- 务必监听
reader.onerror和reader.onabort,不要只写onload - 对 >50MB 的文件,建议先用
URL.createObjectURL(blob)生成临时链接,让用户下载或预览,而非强求转 Base64 - 如果业务真要传 Base64(比如微信 JS-SDK 上传),优先走分片 + 后端接收,前端别扛整块
示例:安全提取纯 Base64 字符串
下面这段代码处理了空 Blob、读取出错、前缀截取等边界:
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const dataUrl = reader.result;
if (typeof dataUrl !== 'string') return reject(new Error('readAsDataURL failed'));
const base64 = dataUrl.split(',')[1];
resolve(base64);
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
调用时注意:blobToBase64(myBlob).then(str => console.log(str.length))——str 就是干净的 Base64 字符串,可直接塞进 src 或 API body。
容易被忽略的是:Blob 的 type 属性会影响 readAsDataURL() 输出的 MIME 前缀,如果构造 Blob 时没传 {type: 'image/png'},默认是 '',结果就是 data:;base64,...,部分老系统解析可能出问题。











