前言
简单介绍一下 Base64 和 File、Blob 对象,及三者之间如何相互转换。
一、概念
- Base64
对于一个典型的 Base64 数据 URL,它的格式如下:
data:[<mediatype>][;base64],<data>
# 例如
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...
Base64 编码在网络上的一个常见应用是对二进制数据进行编码。解码和编码 Base64 字符串:
- btoa():从二进制数据“字符串”创建一个 Base-64 编码的 ASCII 字符串(“btoa”应读作“binary to
ASCII”) - atob():解码通过 Base-64 编码的字符串数据(“atob”应读作“ASCII to binary”)
- Blob
Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,从 Blob 中读取内容的方法是使用 FileReader。Blob 对象通常在服务端响应文件流时,前端设置请求头 responseType: ‘blob’,可将响应转换成 Blob,一个 Blob 对象示例如下:
- File
File 继承自 Blob,File 对象是 Blob 对象的一个特殊版本,带有一些额外的属性,如 name 和 lastModified。通常文件上传组件如 el-upload 上传成功时得到的是 File 对象,一个 File 对象示例如下:
二、相互转换的工具函数
1. Base64 转 File
export const base64ToFile = (base64, mime, filename) => {
let arr = base64.split(',')
let type = mime || arr[0].match(/:(.*?);/)[1]
let suffix = mine.split('/')[1]
let fileName = filename || `未命名.${suffix}`
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], fileName, { type })
}
- 正则表达式 /: (.*?);/ 用于匹配以冒号 : 开始,后面跟着任意数量的非分号字符 [^;]*,并以分号 ; 结束的字符串。以上方示例的 base64 字符串为例,会匹配 image/png 部分,即 MIME 类型。
- atob 函数解码 base64 编码的字符串后,你会得到一个二进制字符串,即每个字符代表一个字节(8位)的原始二进制数据。
- new Uint8Array(n); // 创建初始化为 0 的,包含 n 个元素的 8 位无符号整型数组。
2. File 转 Base64
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
fileToBase64 函数时,由于它返回一个 Promise,你需要使用 .then() 或 async/await 来处理结果
3. Base64 转 Blob
转换 Blob 和 File 基本相同,因为 File 就是特殊的 Blob
export const base64ToBlob = (dataurl) => {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
4. Blob 转 Base64
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = (e) => {
reject(e);
};
});
}
- Blob 和 File 相互转换
const file = new File([/* data */], "filename.txt", { type: "text/plain" });
const blob = new Blob([file]);
const blob = new Blob([/* data */], { type: "text/plain" });
const file = new File([blob], "filename.txt", { type: blob.type, lastModified: Date.now() });