浏览器端文件操作 file base64 blob ArrayBuffer

2,518 阅读3分钟

前端要在浏览器中操作一些文件,这里记录一下常用相互转换的方法,比如file base64 blob ArrayBuffer之间的相互转换。并且记录一些常用转换文件的方法

转 file

base64 转 file

// 此方法需要base64头部信息,文件名不需要扩展名。适用图片、pdf文件、txt文件。
// 通过 fileToBase64 转换的,带头部信息
const dataUrlToFile = function (urlData, filename) { // 64转file
  if (typeof urlData != 'string' || !filename) {
    console.log("参数不正确")
    return;
  }
  const [u8arr, type] = dataUrlToBuffer(urlData)
  const fileExt = type.split('/')[1]
  return new File([u8arr], `${filename}.${fileExt}`, {
    type: type
  });
}

// 一个文件的纯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缺少头部,当需要头部的时候需要加上,比如

  • jpg图片:data:image/jpeg;base64,
  • png图片:data:image/png;base64,
  • excel文件:data:application/vnd.ms-excel;base64,
  • txt文件:data:text/plain;base64,
  • word文件:data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,
  • pdf文件:data:application/pdf;base64,

blob 转 file

const blobToFile = (blob, fileName, options = {}) => {
    return new File([blob], fileName, options)
}

ArrayBuffer 转 file

const arrayBufferToFile = blobToFile

转base64

file 转 base64

转换后带有头部信息

const fileToBase64 = (file) => {
    return new Promise((resolve) => {
        const reader = new FileReader()
        reader.onload = function(result) {
            resolve(result.target.result)
        }
        reader.readAsDataURL(file)
    })
}

blob 转 base64

转换后带有头部信息

const blobToBase64 = fileToBase64

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);
}

转 blob

file 转 blob

const fileToBlob = (file, type = '') => {
    return new Blob([file],{ type:'image/png' })
}

fileToBlob(file, 'image/png')

base64 转 blob

// 带头部的base64(dataUrl)
const dataUrlToBlob = (dataURI) => {  
    const [u8arr, type] = dataUrlToBuffer(dataURI)
    return new Blob([u8arr], {type})
}
// 纯base64,需要指定类型,比如 text/plain,取`data:xxxxxx;base64,` xxx部分
const base64ToBlob = (base64, type = '') => {
    const u8arr = base64ToBuffer(base64) 
    return new Blob([ab], {type})
}

ArrayBuffer 转 blob

const arrayBufferToBlob = fileToBlob

转 ArrayBuffer

file 转 ArrayBuffer

const fileToArrayBuffer = (file) => {
    return new Promise((resolve) => {
        let reader = new FileReader()
        reader.onload = function(result) {
            resolve(result.target.result)
        }
        reader.readAsArrayBuffer(file)
    })
}

base64 转 ArrayBuffer

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;
}
const dataUrlToBuffer = (urlData) => {
    const [head, base64] = urlData.split(',')
    const type = head.match(/:(.*?);/)[1]
    
    return [base64ToBuffer(base64), type]
}

blob 转 ArrayBuffer

const blobToArrayBuffer = fileToArrayBuffer

上诉总结

  • base64在转成其他类型之前首先要转换成ArrayBuffer
  • DataURL&ObjectURL
    • 其中mediatype是表示MIME类型的字符串,默认值为"text/plain;charset=US-ASCII"
    • BlobURL的格式是blob:域名/uuid,需要先将其他格式转换成file或者blob。
    • DataURL的格式是data:[[;base64],
    • 前者长度往往更短,因为后者的数据中存储着图片的base64编码
    • 我们可以直接将DataURL复制到浏览器地址栏进行访问,但BlobURL则不能

canvas 转图片

// canvas.toDataURL 返回的是一串Base64编码的URL
// PND:image/png    jpg:image/jpeg
const missionImg = document.getElementById('canvas').toDataURL('image/png', 1.0);

下载

var a = document.createElement('a');
a.download = '文件.jpg';  //下载的文件名,默认是'下载'
a.href = missionImg; 
document.body.appendChild(a);
a.click();
a.remove();  //下载之后把创建的元素删除

canvas中画了一个跨域图片进去的时候最好是把文件转换成base64再去画图,防止使用toDataURL的时候跨域

作为图片显示

const image = new Image();
image.src = missionImg;
$('#img').append(img);

axios读取文件(小心跨域)

当遇到跨域的时候需要通过服务端处理(接口返回、nginx反向代理),推荐接口返回能安全的很

try {
    // 读取的文件是字符串类型
    // 请求头 response 中 { responseType: 'arraybuffer'}
    // 请求文本文件的时候responseType为空,或者 text,也不需要转化为blob
    const res = await axios.get(fileUrl, {responseType: 'arraybuffer'});
    // 转换为blob方便后续操作
    const blob = new Blob([res.data]);
} catch (error) {
    console.log(error, '获取文件失败');
};

直接获取blob

try {
    // 请求头中 response 的类型 { responseType: 'blob'}
    const res = await axios.get(fileUrl, {responseType: 'blob'});
    const blob = res.data;
} catch (error) {
    console.log(error, '获取文件失败');
};

转化为url并下载

var a = document.createElement('a');
var fileurl = URL.createObjectURL(blob)

var a = document.createElement('a');
a.download = 'filename.xls';
a.href = fileurl;
a.click();
URL.revokeObjectURL(fileurl);

js-xlsx 读取Excel文件

try {
    const res = await axios.get(fileUrl, {responseType: 'blob'});

    const blob = res.data;

    const fileReader = new FileReader();
    fileReader.onload = (ev) => {
        const data = ev.target.result;
        //console.log(data)
        const workbook = XLSX.read(data, {type: 'binary'});
        console.log(workbook.Sheets);
        for (const sheet in workbook.Sheets) {
            console.log(sheet);
            if (!workbook.Sheets.hasOwnProperty(sheet)) continue;

            const fromTo = workbook.Sheets[sheet]['!ref'];
            console.log(fromTo);
            const data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
            console.log(data);
        }
    };
    fileReader.readAsBinaryString(blob);

} catch (error) {
    console.log(error);
    this.$nav.error('解析文件失败!');

};

PDF的相关操作

浏览器html代码生成图片保存为PDF并上传 - 掘金 (juejin.cn)

超级推荐

js一张图搞定arrayBuffer/Blob/File/fileReader/canvas/base64的各种转换操作,以及文件上传 - 掘金 (juejin.cn)

image.png

参考

博客