Blob应用场景

523 阅读2分钟

Blob

binary large object,二进制大文件对象,表示一个不可变、原始数据的类文件对象

通过构造函数创建Blob对象

var aBlob = new Blob(array, options);
  • array:一堆数据构成的数组
  • options:设置一些属性,主要是type属性

属性

  • size:数据的字节大小(只读)

  • type:数据的MIME类型,例如'image/jpeg'(只读)

方法

slice方法,对文件进行分割

Blob.slice(start, end ,contentType)
  • start:分割起始点
  • end: 分割终点
  • contentType:新的MIME类型

应用

  1. 文件下载
  2. 图片预览
  3. 资源分段上传
  4. 本地读取文件

文件下载

通过URL.createObjectURL(blob)生成Blob URL,赋值给a.download属性

普通的字符串是不能被下载的,所以需要将其转换成文件类型的格式,创建二进制对象的URL地址(浏览器内部的"引用",伪协议),赋值给a链接,设置download属性,就可以下载了

<a id="a1">点击下载</a>
const a1 = document.getElementById('a1');
// 定义一个字符串作为文件下载的内容
const content = '<div>content</div>';

const blob = new Blob([content], {
  // 格式为html
  type: 'text/html'
})
// 下载资源的URL,点击会跳转到content对应的html
a1.href = URL.createObjectURL(blob);
// 设置download属性,才可以下载
a1.setAttribute('download', 'index.html');

可以封装一个下载的工具函数,解析blob响应内容并下载

export function resolveBlob(data, mimeType, filename) {
  const aLink = document.createElement('a')
  var blob = new Blob([data], { type: mimeType })
  aLink.href = URL.createObjectURL(blob)
  aLink.setAttribute('download', filename) // 设置下载文件名称
  document.body.appendChild(aLink)
  aLink.click()
  document.body.appendChild(aLink)
}

图片预览

  1. 可以使用Blob对象的方法,读取File对象(File继承自Blob,Blob能用的File都能用)

通过URL.createObjectURL(blob)生成Blob URL,赋给img.src属性

const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (e) => {
  const file = e.target.files[0];
  // blob类型的临时URL地址
  const url = URL.createObjectURL(file);
  const img = document.createElement('img');
  img.src = url;
  document.body.appendChild(img);
  img.onload = function () {
    // 释放临时的URL对象
    URL.revokeObjectURL(url);
  }
})
  1. FileReader读取选中文件,将文件解析成base64
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (e) => {
  const file = e.target.files[0];
  const fileReader = new FileReader();
  // 解析成base64编码的格式
  fileReader.readAsDataURL(file);
  fileReader.onload = function () {
    const src = fileReader.result;
    const img = document.createElement('img');
    img.src = src;
    document.body.appendChild(img);
  }
})

资源分段上传

通过blob.slice可以分割二进制数据,递归上传

<input type="file">
<button id="btn1">上传</button>
const btn1 = document.getElementById('btn1');
const chunkSize = 1024 * 10; // 切片大小,单位:字节
let index = 0;

btn1.addEventListener('click', upload)

function upload () {
  const file1 = document.getElementById('file1');
  
  const file = file1.files[0];
  const [fileName, fileExt] = file.name.split('.');
  
  const fileSize = file.size;

  let start = index * chunkSize;
  
  if (start > fileSize) {
    return
  };
  // 切片
  const blob = file.slice(start, start + chunkSize);
  
  const blobName = `${ fileName }.${index}.${fileExt}`;
  
  // blob -> file
  const blobFile = new File([blob], blobName);

  const formData = new FormData();
  formData.append('file', blobFile);
  
  axios.post('/upload', formData).then(() => {
    index++;
    upload(); // 递归
  })
}

本地读取文件

FileReader的API可以将Blob或File转换为文本/ArrayBuffer/Data URL等类型

  • FileReader.readAsText(Blob):将Blob转化为文本字符串

  • FileReader.readAsArrayBuffer(Blob): 将Blob转为ArrayBuffer格式数据

  • FileReader.readAsDataURL(): 将Blob转化为Base64格式的Data URL