前端中的二进制及相关操作和转换最近工作中遇到了很多二进制处理,比如PDF生成,多PDF打包,音频拼接.为了数据的一致性和降低与后端通信的复杂度,工作量在浏览器端。浏览器,或者说前端,处理的更多的是View层,也就是UI=f(state),state到interface的转换。但是也有很多二进制处理,比如下载一个Excel文档生成PDF,打包多个文件下载乱码图片等。本文总结了浏览器端二进制与相关数据之间的转换,如ArrayBuffer、TypedArray、Blob、DataURLObjectURL与Text之间的转换。为了更好的理解和方便以后的查询,我特意做了一张图来总结一下。原文链接见http://shanyue.tech/post/binary-in-frontend/Binary-in-frontend相关数据类型。描述二进制数据的类数组数据结构。但它本身不能被实例化甚至访问。你可以理解为抽象类或接口。基于TypedArray,有以下数据类型。Uint8ArrayUint表示数组的每一项都是无符号整数8表示每一项数据占8位,即一个字节Int8ArrayUint8ArrayInt16Array...constarray=newInt8Array([1,2,3])//。length表示数据大小//3array.length//.btyeLength表示数据数组占用的字节大小。byteLengthArrayBuffer表示二进制数据结构,只读。需要转为TypedArray进行操作。constarray=newInt16Array([1,2,3])//TypedArray->ArrayBufferarray.buffer//ArrayBuffer->TypedArraynewInt16Array(array.buffer)//buffer.length表示数据占用的字节大小array.buffer.length===array.byteLengthconcatenatesmultipleTypedArraysTypedArray没有Array.prototype.concat方法可以像数组一样连接多个TypedArray。但是,它提供了TypedArray.prototype.set可用于间接连接字符串。可以参考MDN文档:https://developer.mozilla.org...//将typedarray放在offset位置typedarray.set(typedarray,offset)的原理是首先分配一个足够的空间来容纳那个TypedArray需要连接,然后叠加functionconcatenate(constructor,...arrays){letlength=0;for(letarrofarrays){length+=arr.length;}letresult=newconstructor(length);让偏移量=0;for(letarrofarrays){result.set(arr,offset);偏移量+=arr.length;}returnresult;}concatenate(Uint8Array,newUint8Array([1,2,3]),newUint8Array([4,5,6]))同时,你还需要对资源获取有个大概的了解,例如XHR、获取和文件上传。BlobBlob是浏览器端的类文件对象。操作blob需要数据类型FileReader。FileReader有如下方法将Blob转换为其他数据文件blob.sizeconstarray=newUint8Array([128,128,128])constblob2=newBlob([array])functionreadBlob(blob,type){returnnewPromise(resolve=>{constreader=newFileReader()reader.onload=function(e){resolve(e.target.result)}reader.readAsArrayBuffer(blob)})}readBlob(blob,'DataURL').then(url=>console.log(url))复制代码datainput数据输入或资源请求可以分为以下两种方式:通过url地址请求网络资源和通过文件上传请求本地资源。fetchfetch大家应该不陌生,但是大多使用单一环境,一般用于请求json数据。其实也可以设置返回数据格式为Blob或者ArrayBuffer。fetch返回一个包含Response对象的Promise,Response有如下方法Response.prototype.arrayBufferResponse.prototype.blobResponse.prototype.textResponse.prototype.json详情请参考MDN文档https://developer.mozilla.org。..fetch('/api/ping').then(res=>{//trueconsole.log(resinstanceofResponse)//最常见的用法returnres.json()//returnBlob//returnres.blob()//ReturnArrayBuffer//returnres.arrayBuffer()})此外,ResponseAPI可以使用TypedArray、Blob、Text作为输入和输出。也就是说这三种数据类型的转换都可以通过Responsexhrxhr来完成。可以设置responseType以接收适当的数据类型。constrequest=newXMLHttpRequest()request.responseType='arraybuffer'request.responseType='blob'File本地文件可以输入[type=file]来上传文件。Hello%2C%20World!
Base64编码与解码Base64使用大小写字母、数字、+和/64characters对数据进行编码,所以称为Base64。编码后,文字大小会变大1/3。在浏览器中,您可以使用atob和btoa编码来解码数据。//aGVsbG8=btoa('hello')ObjectURL可以使用浏览器的新APIURL对象生成地址来表示Blob数据。//粘贴生成的地址,即可访问hello,world//blob:http://host/27254c37-db7a-4f2f-8861-0cf9aec89a64URL.createObjectURL(newBlob('hello,world'.split('')))下载数据:application/octet-stream;base64、5bGx5pyI资源下载可以使用FileSaver。这里还有一个简单的函数来下载链接functiondownload(url,name){consta=document.createElement('a')a.download=namea.rel='noopener'a.href=url//触发模拟clicka.dispatchEvent(newMouseEvent('click'))//ora.click(}二进制数据转换以上是二进制数据之间的转换图,有的可以直接通过API转换,有的需要代码,下面贴几个String到TypedArray的常见转换代码根据上图,string到TypedArray的转换可以通过String->Blob->ArrayBuffer->TypedArray来完成。关于代码中的函数readBlob,可以把链接数据类型转回去——Blobconstname='MountainMoon'constblob=newBlob(name.split(''))readBlob(blob,'ArrayBuffer').then(buffer=>newUint8Array(buffer))也可以直接通过ResponseAPI转换String->ArrayBuffer->TypedArrayconstname='MountainMoon'newResponse(name).arrayBuffer(buffer=>newUint8Array(buffer))以上两个方法直接通过API进行转换,如果你想了解如何手动将字符串和二进制TypedArrayString转换为TypedArray2使用enodeURIComponent将字符串转换为utf8,然后构造TypedArray。函数stringToTypedArray(s){conststr=encodeURIComponent(s)constbinstr=str.replace(/%([0-9A-F]{2})/g,(_,p1)=>{returnString.fromCharCode('0x'+p1)})returnnewUint8Array(binstr.split('').map(x=>x.charCodeAt(0)))}实践一、如何上传本地图片并显示在网页上转换图的获取方式是本地上传图片->Blob->ObjectURL2。如何拼接两个音频文件。上面整理的转换映射的获取方式是获取音频资源->ArrayBuffer->TypedArray->拼接成一个TypedArray->ArrayBuffer->Blob->ObjectURL3。如何将json数据转换成demo.json并下载文件。JSON被认为是一个字符串。从上面整理的转换图来看,路径Text->DataURL除了DataURL下载外,还可以转换成ObjectURL。下载功能下载可以参考上面的链接DataOutput-DownloadText->Blob->ObjectURL可以直接在控制台粘贴以下代码下载文件constjson={a:3,b:4,c:5}conststr=JSON.stringify(json,null,2)constdataUrl=`data:,${str}`consturl=URL.createObjectURL(newBlob(str.split('')))下载(dataUrl,'demo.json')下载(url,'demo1.json')
