JS中各类型文件转换方式汇总
一、格式分类
1、格式种类
ArrayBuffer
File
Blob
DataURL(base64)
OjectURL 用法
canvas (img)
文件流的各种转化图
2、DataURL与ObjectURL的区别
Data URL和Object URL是JavaScript中用于处理数据的两种不同的URL格式。
Data URL是一种将数据嵌入到URL中的格式。它的语法是以"data:"开头,后面跟着数据的MIME类型和Base64编码的数据。例如,一个Data URL可能看起来像这样:data:image/png;base64,iVBORw0KG…(后面是一长串的Base64编码数据)。Data URL适用于将小量的数据直接嵌入到网页中,如图像或CSS样式。
Object URL则是一种在JavaScript中创建指向Blob或File对象的URL的格式。Blob对象是一种表示二进制数据的数据类型,而File对象则是Blob的子类,表示从用户计算机上选择的文件。Object URL的创建是通过调用URL.createObjectURL方法来完成的,传入一个Blob或File对象作为参数。Object URL的格式是以"blob:"开头,后面跟着一个唯一的标识符。例如:blob:https://example.com/12345。Object URL适用于操作大量数据或需要动态创建URL的场景,比如预览用户上传的图像或音视频文件。
Data URL用于将数据直接嵌入到URL中,适用于小量的数据,而Object URL用于创建指向二进制数据的URL,适用于大量数据或需要动态生成URL的情况。
Base64(DataURL)
1、类型介绍
在JavaScript中,Base64 是一组相似的二进制到文本(binary-to-text)的编码规则。它将二进制数据转换为一系列可打印的ASCII字符,以便在文本环境中传输和处理。Base64编码使用64个字符(A-Z、a-z、0-9和+ /)来表示6位二进制数据。
在文件格式中,Base64编码通常用于将二进制文件(如图像、音频或视频)转换为文本字符串。这可以方便地在文本协议(如HTTP)中传输二进制数据,或在文本环境中存储和处理二进制数据。
请注意,Base64编码会导致数据的大小增加约1/3。这是因为每3个字节的二进制数据被编码为4个字符的Base64字符串。
在 JavaScript 中,有两个函数被分别用来处理解码和编码 Base64 字符串:
- atob():解码通过 Base-64 编码的字符串数据(“atob”应读作“ASCII to binary”)
- btoa():从二进制数据“字符串”创建一个 Base-64 编码的 ASCII 字符串(“btoa”应读作“binary to ASCII”)
2、Base64 转 File
不带头部,纯base64情况:
// 一个文件的纯base64,无头部信息,文件格式需要指定,文件名需要带上扩展名。普遍适用
const base64ToFile = function (base64, filename, type) {
if (typeof base64 != 'string' || !filename || !type) {
console.log("参数不正确")
return;
}
const u8arr = base64ToBuffer(base64)
return new File([u8arr], filename, {
type: type
});
}
带头部的base64情况:
//如果base64包含头部信息,则需要将文件类型与文件流通过split()拆分
function base64ToFile(fileDataURL, filename) {
let arr = fileDataURL.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {
type: mime });
}
e.g.
base64ToFile('data:text/plain;base64,YWFhYWFhYQ==...', '测试文件')
Promise写法:
function base64ToFile(base64String, fileName, mimeType) {
return new Promise((resolve, reject) => {
if(base64String != 'string' || !fileName || !mimeType){
reject('参数不正确')
}
const byteCharacters = atob(base64String);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
const slice = byteCharacters.slice(offset, offset + 512);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const fileData = new Blob(byteArrays, {
type: mimeType });
const file = new File([fileData], fileName, {
lastModified: Date.now() });
resolve(file);
});
}
e.g.
const base64String = "SGVsbG8gd29ybGQh";
const fileName = "hello.txt";
const mimeType = "text/plain";
base64ToFile(base64String, fileName, mimeType)
.then(file => {
console.log(file);
})
.catch(error => {
console.error(error);
});
3、Base64 转 Blob
不带头部,纯base64情况:
// 带头部的base64(dataUrl)
const base64ToBlob = (dataURI) => {
const [u8arr, type] = dataUrlToBuffer(dataURI)
return new Blob([u8arr], {
type})
}
带头部的base64情况:
// 纯base64,需要指定类型,比如 text/plain,取`data:xxxxxx;base64,` xxx部分
const base64ToBlob = (base64, type = '') => {
const u8arr = base64ToBuffer(base64)
return new Blob([ab], {
type})
}
Promise写法:
function base64ToBlob(base64String, mimeType) {
return new Promise((resolve, reject) => {
if(base64String != 'string' || !mimeType){
reject('参数为空!')
}
const byteCharacters = atob(base64String);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
const slice = byteCharacters.slice(offset, offset + 512);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {
type: mimeType });
resolve(blob);
});
}
e.g.
const base64String = "SGVsbG8gd29ybGQh";
const mimeType = "text/plain";
base64ToBlob(base64String, mimeType)
.then(blob => {
console.log(blob);
})
.catch(error => {
console.error(error);
});
4、Base64 转 ArrayBuffer
不带头部,纯base64情况:
const base64ToBuffer = (base64String) => {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
带头部的base64情况:
const dataUrlToBuffer = (urlData) => {
const [head, base64] = urlData.split(',')
const type = head.match(/:(.*?);/)[1]
return [base64ToBuffer(base64), type]
}
5、Base64 转 Canvas
//带头部的base64情况,Promise写法
function base64ToCanvas (dataUrl) {
return new Promise(resolve => {
const img = new Image()
img.src = dataUrl
img.onload = function () {
const canvas = document.createElement('canvas')
canvas.width = this.width
canvas.height = this.height
const ctx = canvas.getContext('2d')
ctx.drawImage(this, 0, 0)
resolve(canvas)
}
})
}
e.g.
const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUh...'
base64ToCanvas(dataUrl)
.then(res => document.body.appendChild(res))
Blob
1、类型介绍
Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是 JavaScript 原生格式的数据。File
接口基于 Blob
,继承了 blob 的功能并将其扩展以支持用户系统上的文件。
Blob 对象是包含有只读原始数据的类文件对象。简单来说,Blob 对象就是一个不可修改的二进制文件。
1)创建Blob
const blob = new Blob(array, options)
需要两个参数:
- array:是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体。
- options:可选的 BlobPropertyBag 字典,它可能会指定如下两个属性:
- type:默认值为 “”,表示将会被放入到 blob 中的数组内容的 MIME 类型。
- endings:默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入,不常用。
常用的 MIME 类型如下:
MIME 类型 | 说明 |
---|---|
text/plain | 纯文本文档 |
text/html | HTML文档 |
text/javascript | JavaScript文件 |
text/css | CSS文件 |
application/json | JSON文件 |
application/pdf | PDF文件 |
application/xml | XML文件 |
image/jpeg | JPEG图像 |
image/png | PNG图像 |
image/gif | GIF图像 |
image/svg+xml | SVG图像 |
audio | MP3文件 |
video | MP4文件 |
2)Blob分片
const blob = instanceOfBlob.slice([start [, end [, contentType]]])
需要两个参数:
- start:可选,切片起点,默认值为 0
- end:可选,切片结束位置,默认值为
blob.size
- contentType:可选,设置新 blob 的 MIME 类型。如果省略 type,则默认为 blob 的原始值
// 切片示例:页面上会显示:Hello Wo
const iframe = document.getElementsById("iframe")
const blob = new Blob(["Hello World"], {
type: "text/plain" })
const subBlob = blob.slice(0, 8)
iframe.src = URL.createObjectURL(subBlob)
2、Blob 转 Flie
const blobToFile = (blob, fileName, type) => {
return new File([blob], fileName, {
type })
}
e.g.
blobToFile('test info', 'test', 'text/plain' )
3、Blob 转 Base64
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function() {
const base64Data = reader.result.split(',')[1]; // 去除"data:image/*;"前缀
resolve(base64Data);
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
e.g.
const myBlob = new Blob(["Hello, world!"], {
type: "text/plain;charset=utf-8"});
blobToBase64(myBlob)
.then(base64String => console.log('Base64 String:', base64String))
.catch(error => console.error('Error converting to Base64:', error));
4、Blob 转 ArrayBuffer
function blobToArrayBuffer (blob) {
const reader = new FileReader()
reader.readAsArrayBuffer(blob)
reader.onload = () =>{
return reader.result;
}
}
e.g.
let blob = new Blob([1, 2, 3, 4, 5])
blobToArrayBuffer(blob, (arrayBuffer) => {
console.log(arrayBuffer) })
5、Blob 转 Object URL
function createObjectURLFromBlob(blob) {
return URL.createObjectURL(blob);
}
File
1、类型介绍
文件(File)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。比如说, FileReader
, URL.createObjectURL()
, createImageBitmap()
(en-US), 及 XMLHttpRequest.send()
都能处理 Blob 和 File。
以下为 FileReader
的对象方法:
方法 | 说明 |
---|---|
FileReader.abort() | 中止读取操作。在返回时,readyState属性为DONE |
FileReader.readAsArrayBuffer() | 开始读取指定的 Blob中的内容。完成后,result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象。 |
FileReader.readAsBinaryString() | 开始读取指定的Blob中的内容。完成后,result属性中将包含所读取文件的原始二进制 数据 |
FileReader.readAsDataURL() | 开始读取指定的Blob中的内容。完成后,result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容 |
FileReader.readAsText() | 开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串 以表示所读取的文件内容 |
2、File 转 Base64
async function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function() {
const base64Data = reader.result.split(',')[1]; // 去除"data:image/*;base64,"前缀
resolve(base64Data);
};
reader.onerror = reject;
reader.readAsDataURL(file); // 读取文件为DataURL,即Base64编码形式
});
}
// 使用示例
document.getElementById('fileInput').addEventListener('change', async (event) => {
const file = event.target.files[0];
try {
const base64String = await fileToBase64(file);
console.log('Base64 String:', base64String);
} catch (error) {
console.error('Error converting to Base64:', error);
}
});
3、File 转 Blob
const fileToBlob = (file, type = '') => {
return new Blob([file],{
type:'image/png' })
}
e.g.
fileToBlob(file, 'image/png')
4、File 转 ArrayBuffer
const fileToArrayBuffer = (file) => {
return new Promise((resolve) => {
let reader = new FileReader()
reader.onload = function(result) {
resolve(result.target.result)
}
reader.readAsArrayBuffer(file)
})
}
5、File 转 Object URL
function fileToObjectURL(file) {
return URL.createObjectURL(file);
}
ArrayBuffer
1、类型介绍
ArrayBuffer 是 JavaScript 中用于处理二进制数据的一个底层接口,它代表了一段固定长度的二进制数据缓冲区。虽然 ArrayBuffer 本身不提供直接读写数据的方法,但它为多种类型化的数组(Typed Arrays)提供了基础,使得开发者能够以各种基本数据类型(如无符号整数、有符号整数、浮点数等)来操作这些二进制数据。
2、ArrayBuffer 转 File
/**
arrayBuffer:需要转换的ArrayBuffer实例。
fileName:生成的File对象的名称。
mimeType:可选,指定生成的File对象的MIME类型,默认为application/octet-stream,表示通用的二进制文件
*/
function arrayBufferToFile(arrayBuffer, fileName, mimeType = 'application/octet-stream') {
// 创建一个Blob对象,使用ArrayBuffer数据和指定的MIME类型
const blob = new Blob([arrayBuffer], {
type: mimeType });
// 使用Blob对象和文件名创建File对象
const file = new File([blob], fileName, {
lastModified: Date.now() });
return file;
}
3、ArrayBuffer 转 base64
转换后没有头部
const arrayBufferToBase64 = (buffer) => {
return window.btoa(String.fromCharCode(...new Uint8Array(buffer)))
}
转换后没有头部
function arrayBufferToBase64 (buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
for (let len = bytes.byteLength, i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
4、ArrayBuffer 转 Blob
/**
rrayBuffer:需要转换的ArrayBuffer实例。
mimeType:可选参数,指定生成的Blob对象的MIME类型,默认为空字符串,表示未知或不指定类型。
*/
function arrayBufferToBlob(arrayBuffer, mimeType = '') {
return new Blob([arrayBuffer], {
type: mimeType });
}
5、ArrayBuffer 转 Object URL
function arrayBufferToObjectURL(arrayBuffer, mimeType = '') {
// 将ArrayBuffer转换为Blob
const blob = new Blob([arrayBuffer], {
type: mimeType });
// 使用Blob创建Object URL
const objectURL = URL.createObjectURL(blob);
return objectURL;
}
Object URL
1、类型介绍
Object URL(MDN 定义名称)又称 Blob URL(W3C 定义名称),是 HTML5 中的新标准。它是一个用来表示 File Object 或 Blob Object 的 URL。
Blob URL/Object URL 是一种伪协议,允许将 Blob 和 File 对象用作图像、二进制数据下载链接等的 URL 源。
<!-- 通过 Object URL 展示和下载图片 -->
<!DOCTYPE html>
<html lang="en">
<body>
<input type="file" id="input" />
<img id="img" />
<script>
const input = document.getElementById("input");
const img = document.getElementById("img");
input.onchange = (e) => {
const url = URL.createObjectURL(e.target.files[0]);
img.src = url;
// 实现下载
const a = document.createElement("a");
a.href = url;
a.download = "img";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
</script>
</body>
</html>
2、Object URL 转 Base64
async function objectURLToBase64(objectURL) {
// 通过fetch获取Blob
const response = await fetch(objectURL);
const blob = await response.blob();
// 使用FileReader读取Blob为Base64
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
3、Object URL 转 Blob
async function objectURLToBlob(objectURL) {
// 使用fetch API从Object URL获取响应,然后转换为Blob
const response = await fetch(objectURL);
const blob = await response.blob();
return blob;
}
4、Object URL 转 File
async function objectURLToFile(objectURL, fileName) {
// 使用fetch获取Blob
const response = await fetch(objectURL);
const blob = await response.blob();
// 将Blob转换为File对象
const file = new File([blob], fileName, {
type: blob.type });
return file;
}
5、Object URL 转 ArrayBuffer
async function objectURLToArrayBuffer(objectURL) {
// 使用fetch获取Blob
const response = await fetch(objectURL);
const blob = await response.blob();
// 创建一个 FileReader 对象来读取 Blob
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function() {
// FileReader.onload 触发时,e.target.result 包含了ArrayBuffer
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsArrayBuffer(blob);
});
}
Canvas
1、绘制Canvas
function fileAndBlobToCanvas(fileDataURL) {
let img = new Image()
img.src = fileDataURL
let canvas = document.createElement('canvas')
if (!canvas.getContext) {
alert('浏览器不支持canvas')
return
}
let ctx = canvas.getContext('2d')
document.getElementById('container').appendChild(canvas)
img.onload = function () {
ctx.drawImage(img, 0, 0, img.width, img.height)
}
}
2、Canvas 转Base64
function canvasToDataURL() {
let canvas = document.createElement('canvas')
let canvasDataURL = canvas.toDataURL('image/png', 1.0)
return canvasDataURL
}
//这个方法返回的是图片base64,用来生成图片的,默认png格式,也可以通过传递参数改变图片格式,还能改变图片保存的质量。
如:canvas.toDataURL(“images/jpeg”,0) ,第一个参数就是把图片编码为jpeg格式,第二个参数(0-1)就是指定图片质量,数值越大质量越高,不过对于image/png格式没法设置图片质量。
另外,chrome还支持自家的image/webp格式图片,也能设置图片质量。
function canvasToDataURL (file) {
return new Promise(resolve => {
const img = document.createElement('img')
img.src = URL.createObjectURL(file)
img.onload = function () {
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
resolve(canvas.toDataURL('image/png', 1))
}
})
}
3、Canvas 转 Blob
// html
<input type="file" accept="image/*" id="file">
// js
document.querySelector('#file').onchange = function () {
canvasToDataURL(this.files[0])
.then(res => console.log(res))
}
function canvasToDataURL (file) {
return new Promise(resolve => {
const img = document.createElement('img')
img.src = URL.createObjectURL(file)
img.onload = function () {
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
canvas.toBlob(function (e) {
resolve(e)
}, 'image/png', 1)
}
})
}
总结
base64
在转成其他类型之前首先要转换成ArrayBuffer
- 适用性最广的是
Blob
类型,部分类型之间无法直接转换,都需要通过Blob类型中间过渡,因此只需要掌握Blob与其他类型的转换,即可掌握其他类型的转换。 - DataURL&ObjectURL
- 其中mediatype是表示MIME类型的字符串,默认值为"text/plain;charset=US-ASCII"
- BlobURL的格式是
blob:域名/uuid
,需要先将其他格式转换成file或者blob。 - DataURL的格式是
data:[[;base64],
- 前者长度往往更短,因为后者的数据中存储着图片的base64编码
- 我们可以直接将DataURL复制到浏览器地址栏进行访问,但BlobURL则不能
引用
https://juejin.cn/post/7217304466076319800#heading-1
https://juejin.cn/post/7067865471273893902#heading-0