浅谈Blob及使用场景

一、Blob是什么

在一般的Web开发中,很少会用到Blob,但Blob可以满足一些场景下的特殊需求。Blob,Binary Large Object的缩写,代表二进制类型的大对象。Blob的概念在一些数据库中有使用到,例如,MYSQL中的BLOB类型就表示二进制数据的容器。在Web中,Blob类型的对象表示不可变的类似文件对象的原始数据,通俗点说,就是Blob对象是二进制数据,但它是类似文件对象的二进制数据,因此可以像操作File对象一样操作Blob对象,实际上,File继承自Blob。

最早是数据库直接用Blob来存储二进制数据对象,这样就不用关注存储数据的格式了。在web领域,Blob对象表示一个只读原始数据的类文件对象,虽然是二进制原始数据但是类似文件的对象,因此可以像操作文件对象一样操作Blob对象。

ArrayBuffer对象用来表示通用的、固定长度的原始二进制数据缓冲区。我们可以通过new ArrayBuffer(length)来获得一片连续的内存空间,它不能直接读写,但可根据需要将其传递到TypedArray视图或 DataView 对象来解释原始缓冲区。实际上视图只是给你提供了一个某种类型的读写接口,让你可以操作ArrayBuffer里的数据。TypedArray需指定一个数组类型来保证数组成员都是同一个数据类型,而DataView数组成员可以是不同的数据类型。

二、Blob API 简介

Blob - Web API 接口参考 | MDN

三、Blob 使用场景

3.1、分片上传

大文件分片上传前后端实现_程序员小潘-CSDN博客

利用Blob进行文件上传的完整步骤_微若轻澜的博客-CSDN博客

3.2、使用插件

Web Uploader支持多图上传,大文件上传,压缩图片上传,拖拽上传,显示上传进度,预览等。当上传的需求要求可预览、显示上传进度、中断上传过程、大文件分片上传等等,这时传统的表单上传很难实现这些功能,我们可以借助现有插件完成。

3.2、从互联网下载数据

// Blob--内容转化为文件下载
export const fileDownload = (file, fileName = '下载文件', options) => {
  // 创建隐藏的可下载链接
  let eleLink = document.createElement('a')
  eleLink.download = fileName
  eleLink.style.display = 'none'
  // 字符内容转变成blob地址
  let blob = options ? new Blob([file], options) : new Blob([file])
  eleLink.href = URL.createObjectURL(blob)
  // 触发点击
  document.body.appendChild(eleLink)
  eleLink.click()
  // 然后移除
  document.body.removeChild(eleLink)
}
// url地址下载,fileName暂无作用
export const urlDownload = (url, fileName = '下载文件') => {
  // 创建隐藏的可下载链接
  let eleLink = document.createElement('a')
  eleLink.download = fileName
  eleLink.style.display = 'none'
  eleLink.href = url
  // 触发点击
  document.body.appendChild(eleLink)
  eleLink.click()
  // 然后移除
  document.body.removeChild(eleLink)
}

3.3、Blob用作URL

// Blob网址/对象网址只能在浏览器内部制作, 不能在服务器上创建自己的Blob网址
// 可以通过文件读取器API创建Blob并获取File对象,
// 尽管BLOB只是意味着Binary Large对象并以字节数组的形式存储。
// 客户端可以请求数据以ArrayBuffer或Blob的形式发送。
// 服务器应该将数据作为纯二进制数据发送。
// 数据库通常也使用Blob来描述二进制对象,实际上我们基本上是在谈论字节数组。

var blob = new Blob([arrayBufferWithPNG], {type: "image/png"}),
    url = (URL || webkitURL).createObjectURL(blob),
    img = new Image();

img.onload = function() {
    URL.revokeObjectURL(this.src);     // clean-up memory
    document.body.appendChild(this);   // add image to DOM
}

img.src = url;

3.4、url、base64、blob相互转换

3.4.1、url 转  base64

// url 转 base64
// 原理: 利用canvas.toDataURL的API转化成base64
function urlToBase64(url) {
          return new Promise ((resolve,reject) => {
        let image = new Image();
        image.onload = function() {
          let canvas = document.createElement('canvas');
          canvas.width = this.naturalWidth;
          canvas.height = this.naturalHeight;
          // 将图片插入画布并开始绘制
          canvas.getContext('2d').drawImage(image, 0, 0);
          // result
          let result = canvas.toDataURL('image/png')
          resolve(result);
        };
        // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
        image.setAttribute("crossOrigin",'Anonymous');
        image.src = url;
        // 图片加载失败的错误处理
        image.onerror = () => {
          reject(new Error('urlToBase64 error'));
      };
    }
// 调用:
let imgUrL = `http://XXX.jpg`
urlToBase64(imgUrL).then(res => {
  // 转化后的base64图片地址
  console.log('base64', res)
})

3.4.2、base64 转 blob

// 原理:利用URL.createObjectURL为blob对象创建临时的URL
function base64ToBlob ({b64data = '', contentType = '', sliceSize = 512} = {}) {
  return new Promise((resolve, reject) => {
    // 使用 atob() 方法将数据解码
    let byteCharacters = atob(b64data);
    let byteArrays = [];
    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
      let slice = byteCharacters.slice(offset, offset + sliceSize);
      let byteNumbers = [];
      for (let i = 0; i < slice.length; i++) {
          byteNumbers.push(slice.charCodeAt(i));
      }
      // 8 位无符号整数值的类型化数组。内容将初始化为 0。
      // 如果无法分配请求数目的字节,则将引发异常。
      byteArrays.push(new Uint8Array(byteNumbers));
    }
    let result = new Blob(byteArrays, {
      type: contentType
    })
    result = Object.assign(result,{
      // 这里一定要处理一下 URL.createObjectURL
      preview: URL.createObjectURL(result),
      name: `XXX.png`
    });
    resolve(result)
  })
 }
// 调用
let base64 = base64.split(',')[1]
base64ToBlob({b64data: base64, contentType: 'image/png'}).then(res => {
  // 转后后的blob对象
  console.log('blob', res)
})

3.4.3、blob 转 base64

// 原理:利用fileReader的readAsDataURL,将blob转为base64
blobToBase64(blob) {
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
      resolve(e.target.result);
    };
    // readAsDataURL
    fileReader.readAsDataURL(blob);
    fileReader.onerror = () => {
      reject(new Error('blobToBase64 error'));
    };
  });
}
// 调用
blobToBase64(blob).then(res => {
  // 转化后的base64
  console.log('base64', res)
})

3.5、图片压缩

// 图片压缩
// 接收三个参数:
// file:是读取的文件,需要input type="file"获取或者通过js获取
// rate:压缩比例;按照原来图片的百分比
// maxSize: 压缩后的最大文件
// rate有则使用rate,最大限制拦截,会判断rate后是否大于maxSize,如果大于,则剪切,不大于,这rate
// fileType:返回内容的类型;file即压缩后的第一个参数,blob是blob文件,base64是base64文件
// 返回:promise,第一个参数:filePress,即压缩后的fileType文件;第二个参数:base64,即源文件base64
export const imgPress = ({ file, rate = 1, maxSize = 800, fileType = 'file' }) => {
  return new Promise(resolve => {
    // new一个文件读取方法,监听文件读取
    let reader = new FileReader()
    reader.readAsDataURL(file)
    let img = new Image()
    reader.onload = function (e) {
      img.src = e.target.result
    }
    img.onload = function () {
      let canvas = document.createElement('canvas')
      let context = canvas.getContext('2d')
      // 文件大小KB
      const fileSizeKB = file.size / 1024
      // 配置rate和maxSize的关系
      if (fileSizeKB * rate > maxSize) {
        rate = Math.floor(maxSize / fileSizeKB * 10) / 10
      }
      // 缩放比例,默认0.5
      let targetW = canvas.width = this.width * rate
      let targetH = canvas.height = this.height * rate
      context.clearRect(0, 0, targetW, targetH)
      context.drawImage(img, 0, 0, targetW, targetH)
      if (fileType === 'file' || fileType === 'blob') {
        canvas.toBlob(function (blob) {
          resolve({ filePress: fileType === 'blob' ? blob : new File([blob], file.name, { type: file.type }), base64: img.src })
        })
      } else {
        resolve({ filePress: fileType === 'base64' ? canvas.toDataURL(file.type) : null, base64: img.src })
      }
    }
  })
}

3.6、生成PDF

3.7、Blob与ArrayBuffer的区别

Blob 全称:Binary Large Object (二进制大型对象)

Blob 对象表示一个二进制文件的数据内容,通常用来读写文件,比如一个图片文件的内容就可以通过 Blob 对象读写。

与 ArrayBuffer 区别:

Blob 用于操作二进制文件

ArrayBuffer 用于操作内存

3.7.1、ArrayBuffer转Blob

var buffer = new ArrayBuffer(16);
var blob = new Blob([buffer]);

3.7.2、Blob转ArrayBuffer

var blob = new Blob([1,2,3,4,5]);
var reader = new FileReader();

reader.onload = function() {
    console.log(this.result);
}
reader.readAsArrayBuffer(blob);

3.8、Blob(Binary Large Object)表示二进制类型的大对象。

3.9、在数据库管理系统中,将二进制数据存储为Blob。

参考文献:

图片:前端展示图像(img 、picture、svg、canvas )及常用图片格式(PNG、JPG、JPEG、WebP、GIF、SVG、AVIF等)_snow@li的博客-CSDN博客

为什么视频网站的视频链接地址是blob?_llhh33的博客-CSDN博客_blob

 (13条消息) JS___Blob处理二进制数据分片上传_web_blog的博客-CSDN博客

利用Blob进行文件上传的完整步骤_微若轻澜的博客-CSDN博客

(14条消息) 大文件分片上传前后端实现_程序员小潘-CSDN博客

(14条消息) vue+大文件分片上传_Mr_Zang666的博客-CSDN博客

[HTML5] Blob对象 - 好文

webUploader的使用 - 简书

https://segmentfault.com/a/1190000019823978

Vue2.0结合webuploader实现文件分片上传 - 夏大师 - 博客园

url、base64、blob相互转换方法 - 知乎

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值