一、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 使用场景
3.1、分片上传
利用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);