JS中各类型文件(ArrayBuffer、File、Blob、DataURL、OjectURL、canvas )转换方式汇总

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/htmlHTML文档
text/javascriptJavaScript文件
text/cssCSS文件
application/jsonJSON文件
application/pdfPDF文件
application/xmlXML文件
image/jpegJPEG图像
image/pngPNG图像
image/gifGIF图像
image/svg+xmlSVG图像
audioMP3文件
videoMP4文件
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

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值