常见数据转换

323 阅读6分钟

简介

涉及数据类型

  • blob、file
  • ObjectURL
  • DataURL、text、BinaryString、ArrayBuffer

blob、file

blob、file 来源

通常我们得到File和Blob对象,总结有这几种方式:

  • 通过input标签
  • 通过接口获取
  • 拖拽方式
  • canvas获取

input获取file

<input type="file" name="file" id="file">

const inputNode = document.getElementById('file')
inputNode.addEventListener('change', (e) => {
    const file = e.target.files[0]
})

接口获取blob

接口获取需要设置响应头为blob,这里以axios和fetch为例

axios
axios.post(url,{
  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'blob',
})
fetch
fetch(url).then(res=>{
// 常用的有 json、text、arrayBuffer、blob
    return res.blob()
})

拖拽获取文件

<div style="background: #22e7d7; width: 500px; height: 500px; margin: 20px auto">
    <div id="drag" style="width: 100%; height: 100%"></div>
</div>

const dragNode = document.getElementById("drag");
dragNode.ondragover = (e) => {
    e.preventDefault();
};

dragNode.ondrop = (e) => {
    e.preventDefault();
    const files = e.dataTransfer.files;
    console.log(files);
};

canvas获取blob

<canvas id="canvas"></canvas>

const canvas = document.getElementById("canvas");

canvas.toBlob((blob) => {
    console.log(blob);
});

blob和file之间的关系

image.png

创建blob

new Blob(array, options);

参数
  • array:数组,由 ArrayBufferArrayBufferViewBlobDOMString 等对象构成的,将会被放进 Blob
  • options:对象,可以指定如下两个属性
    • type:默认值为 "",表示将会被放入到 blob 中的数组内容的 MIME 类型。
    • endings:默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入,不常用。

常见的 MIME 类型如下:

类型描述
text/plain纯文本文档
text/htmlHTML文档
text/javascriptJavaScript文件
text/cssCSS文件
application/jsonJSON文件
application/pdfPDF文件
application/xmlXML文件
image/jpegJPEG图像
image/pngPNG图像
image/svg+xmlSVG图像
audio/mpegMP3文件
video/mpegMP4文件

ObjectURL

Object URL又称Blob URL(W3C定义名称),是HTML5中的新标准。它是一个用来表示File Object 或Blob Object 的URL。在网页中,我们可能会看到过这种形式的 blob: URL

其实Blob URL/Object URL 是一种伪协议,允许将 Blob 和 File 对象用作图像、二进制数据下载链接等的 URL 源。

对于 Blob/File 对象,可以使用 URL构造函数的 createObjectURL() 方法创建将给出的对象的 URL。这个 URL 对象表示指定的 File 对象或 Blob 对象。我们可以在<img><script> 标签中或者 <a><link> 标签的 href 属性中使用这个 URL(可以用于实现下载文件)

DataURL、text、BinaryString、ArrayBuffer

Data URL

Data URL是一种包含数据的URL,其中数据部分通常是使用Base64编码的。是一种将小数据嵌入到文档中的方式。它的格式如下:

data:[<mediatype>][;base64],<data>
  • <mediatype>:表示数据的媒体类型(MIME 类型),例如 text/plainimage/png。如果省略,默认值是 text/plain;charset=US-ASCII
  • ;base64:表示数据使用 Base64 编码。如果省略,数据部分应为 URL 编码的字符串。
  • <data>:表示实际的数据部分。

Base64

Base64 是一种基于64个可打印字符来表示二进制数据的表示方法。Base64 编码普遍应用于需要通过被设计为处理文本数据的媒介上储存和传输二进制数据而需要编码该二进制数据的场景。这样是为了保证数据的完整并且不用在传输过程中修改这些数据。

在 JavaScript 中,有两个函数被分别用来处理解码和编码 base64 字符串:

  • atob():解码,解码一个 Base64 字符串;
  • btoa():编码,从一个字符串或者二进制数据编码一个 Base64 字符串。

总结一下:

  • Data URL 是一种将数据嵌入到文档中的 URL 格式,其中数据部分通常使用 Base64 编码。
  • Base64 是一种将二进制数据转换为 ASCII 字符串的编码方式,用于在文本环境中传输二进制数据。

生成Data URL的两种方式

canvas生成DataURL:

const dataUrl = canvas.toDataURL();

使用FileReader的readAsDataURL:

const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
    console.log(e.target.result);
}

Text

字面意思,就是文本

BinaryString

BinaryString指的是以二进制形式表示的数据,并用字符串的方式来存储和操作。这意味着它是一个由字符 '0' 和 '1' 组成的字符串,代表二进制数。

ArrayBuffer

ArrayBuffer 是 JavaScript 中用于处理二进制数据的对象。它代表一个通用的、固定长度的原始二进制数据缓冲区,可以用于处理各种类型的二进制数据,如图像、音频、网络协议等。

数据转换

blob、file转ObjectURL

经典下载代码

// 使用 URL.createObjectURL 创建一个 URL 对象 
const url = URL.createObjectURL(blob); 
// 创建一个 <a> 标签并设置下载属性 
const a = document.createElement('a'); 
a.href = url; 
a.download = 'hello.txt'; // 设置下载的文件名 
// 模拟点击 <a> 标签 
document.body.appendChild(a); 
a.click(); 
// 移除 <a> 标签并释放 URL 对象 
document.body.removeChild(a); 
URL.revokeObjectURL(url);

blob、file转DataURL、Text、BinaryString、ArrayBuffer

FileReader

先了解一下FileReader:

FileReader 允许异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据(也就是可以将blob、file转换成其他数据类型)

blob、file转DataURL

const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
    console.log(e.target.result);
}

blob、file转Text

const reader = new FileReader();
reader.readAsText(blob);
reader.onload = function (e) {
    console.log(e.target.result);
}

blob、file转BinaryString

const reader = new FileReader();
reader.readAsBinaryString(blob);
reader.onload = function (e) {
    console.log(e.target.result);
}

blob、file转ArrayBuffer

const reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = function (e) {
    console.log(e.target.result);
}

DataURL、Text、BinaryString、ArrayBuffer四种数据的互相转换

Data URL转换其他三种格式

DataURL -> ArrayBuffer
function dataURLToArrayBuffer(dataURL) {
    const binaryString = atob(dataURL.split(',')[1]);
    const len = binaryString.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes.buffer;
}
DataURL -> BinaryString
function dataURLToBinaryString(dataURL) {
    return atob(dataURL.split(',')[1]);
}
DataURL -> Text
async function dataURLToText(dataURL) {
    const arrayBuffer = dataURLToArrayBuffer(dataURL);
    return arrayBufferToText(arrayBuffer);
}

ArrayBuffer转换其他三种格式

ArrayBuffer -> DataURL
function arrayBufferToDataURL(arrayBuffer, mimeType = 'application/octet-stream') {
    const bytes = new Uint8Array(arrayBuffer);
    const binaryString = bytes.reduce((data, byte) => data + String.fromCharCode(byte), '');
    return `data:${mimeType};base64,${btoa(binaryString)}`;
}
ArrayBuffer -> BinaryString
function arrayBufferToBinaryString(arrayBuffer) {
    const bytes = new Uint8Array(arrayBuffer);
    return bytes.reduce((data, byte) => data + String.fromCharCode(byte), '');
}
ArrayBuffer -> Text
function arrayBufferToText(arrayBuffer) {
    const decoder = new TextDecoder('utf-8');
    return decoder.decode(new Uint8Array(arrayBuffer));
}

BinaryString转换其他三种格式

BinaryString -> ArrayBuffer
function binaryStringToArrayBuffer(binaryString) {
    const len = binaryString.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes.buffer;
}
BinaryString -> DataURL
function binaryStringToDataURL(binaryString, mimeType = 'application/octet-stream') {
    return `data:${mimeType};base64,${btoa(binaryString)}`;
}
BinaryString -> Text
function binaryStringToText(binaryString) {
    return decodeURIComponent(escape(binaryString));
}

Text转换其他三种格式

Text -> ArrayBuffer
function textToArrayBuffer(text) {
    const encoder = new TextEncoder();
    return encoder.encode(text).buffer;
}
Text -> BinaryString
function textToBinaryString(text) {
    return unescape(encodeURIComponent(text));
}
Text -> DataURL
function textToDataURL(text, mimeType = 'text/plain') {
    const arrayBuffer = textToArrayBuffer(text);
    return arrayBufferToDataURL(arrayBuffer, mimeType);
}

通过上述函数,可以实现 Data URLArrayBufferBinary String 和 Text 之间的相互转换。注意在处理不同编码格式和数据类型时,需要根据具体需求调整 TextDecoder 和 TextEncoder 的编码参数。

DataURL、Text、BinaryString、ArrayBuffer四种格式转换为blob格式

DataURL -> Blob

function dataURLToBlob(dataURL) {
    const byteString = atob(dataURL.split(',')[1]);
    const mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0];
    const ab = new ArrayBuffer(byteString.length);
    const ia = new Uint8Array(ab);
    for (let i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], { type: mimeString });
}

ArrayBuffer -> Blob

function arrayBufferToBlob(arrayBuffer, mimeType = 'application/octet-stream') {
    return new Blob([arrayBuffer], { type: mimeType });
}

BinaryString -> Blob

function binaryStringToBlob(binaryString, mimeType = 'application/octet-stream') {
    const ab = new ArrayBuffer(binaryString.length);
    const ia = new Uint8Array(ab);
    for (let i = 0; i < binaryString.length; i++) {
        ia[i] = binaryString.charCodeAt(i);
    }
    return new Blob([ia], { type: mimeType });
}

Text -> Blob

function textToBlob(text, mimeType = 'text/plain') {
    return new Blob([text], { type: mimeType });
}

总结图片

File_Blob.png