关于二进制的一点小思考
栏目: JavaScript · 发布时间: 5年前
内容简介:在这次的公众号项目中,需要一个用户的小程序二维码,一开始想的是实时生成小程序二维码,后台问我行不行,隐约记得微信好像确实提供了这个功能,就答应下来了。一开始以为只需要access_tojen我就可以自己生成了,然而我好像忽略了getWXACodeUnlimit 文档说的是:如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。
在这次的公众号项目中,需要一个用户的小程序二维码,一开始想的是实时生成小程序二维码,后台问我行不行,隐约记得微信好像确实提供了这个功能,就答应下来了。一开始以为只需要access_tojen我就可以自己生成了,然而我好像忽略了 跨域 这件事。没办法,看来还是得 后台中转一下 了。因为后台暂时没空,我就要了appid和secret先自己用node试试效果。
getWXACodeUnlimit 文档说的是:
如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。
2. 问题来了
二进制内容是什么?ArrayBuffer还是Blob?都试试吧。
隐约记得,XHR2可以从服务器获取其他格式的数据了。
值 | 数据类型 |
---|---|
'' | DOMString (这个是默认类型) |
arraybuffer | ArrayBuffer对象 |
blob | Blob对象 |
document | Document对象 |
json | JavaScript object, parsed from a JSON string returned by the server |
text | DOMString |
我一开始还以为如果设置了responseType为Blob的话,返回的是字符串。当时可真的是一顿操作猛如虎,一看结果250。
其实只要查看一下 响应数据的constructor 属性就知道返回数据是什么类型的了,回想起来真的是好尴尬,竟然连这么基础的知识都忘了。
。
废话不多说,下面说我的解决方案吧。
3. 使用Blob作为图片的src
在这里想出来3种办法(_blob为ajax请求得到的Blob对象):
3.1 使用 window.URL 的方法
var src = window.URL.createObjectURL(blob); document.querySelector("#img").setAttribute("src", src) // createObjectURL创建的数据不会自行释放,所以无用的时候还得调用如下方法进行手动释放 window.URL.revokeObjectURL(src) 复制代码
3.2 使用 FileReader 的方法
var reader = new FileReader(); reader.onload = (e) => { document.querySelector("#img").setAttribute("src", reader.result) } reader.readAsDataURL(_blob); 复制代码
3.3 直接将接口地址设置为src的值
// 假设接口的地址是 http://test.com/index/getWxImg // html <img src="http://test.com/index/getWxImg" alt="微信小程序二维码" /> 复制代码
这就相当于在浏览器地址栏直接通过url访问该图片了,他会自动根据响应头的 Content-Type 和 响应数据 进行展示。当然了,这种方式只限于 get 请求,如果接口的请求方式只能是 post, 就只能用前两种方式了。
这次可真是闹了一个大乌龙,痛定思痛,我决定对 ArrayBuffer 和 Blob 进行一个较为深入的理解。
4. 名词解释
4.1 ArrayBuffer(二进制数组)
二进制数组(ArrayBuffer对象、TypedArray视图和DataView视图)是JavaScript操作二进制数据的一个接口。 这个接口的原始设计目的,与WebGL项目有关。所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式。文本格式传递一个32位整数,两端的JavaScript脚本与显卡都要进行格式转化,将非常耗时。这时要是存在一种机制,可以像 C语言 那样,直接操作字节,将4个字节的32位整数,以二进制形式原封不动地送入显卡,脚本的性能就会大幅提升。
4.2 Blob(二进制数据)
Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
Blob的构造函数为 Blob(blobParts[, options])。第一个参数必须为数组,可以是字符串数组,可以是二进制数组。options是一个对象,主要通过设置 type 值来指定文件的 content-type。
简单来说,可以直接把ArrayBuffer当成二进制数组,而把Blob当成是二进制数据。(这么说没错吧?如果理解的不对,欢迎指正。)
5. Blob与其他数据类型的转换
5.1 base64转为Blob
function dataURL2Blob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); } 复制代码
5.2 字符串转为Blob
function plain2Blob(text, type) { return new Blob([text], { type: 'text/plain' }); } 复制代码
5.3 ArrayBuffer转为Blob
function buffer2Blob(_buffer, type) { return new Blob([_buffer], { type: 'application/octet-stream' }); } 复制代码
5.4 Blob转为其他类型
从Blob中读取内容的唯一方法是使用 FileReader 。
var _blob = new Blob([]); //假设它是一个有效的Blob对象 var reader = new FileReader(); reader.onload = (e) => { console.log(reader.result) } 复制代码
reader.readAsDataURL(_blob); reader.readAsText(_blob); reader.readAsArrayBuffer(_blob);
6. 利用Blob下载文件
6.1 下载函数
// @params content: String // @params type: String // @params filename: String function downloadFile(content, type = 'text', filename) { var textBlob; if (type === 'img') { textBlob = dataURL2Blob(content); if (!filename) { throw new Error('type为img时, filename 文件名参数必传'); } } else { textBlob = plain2Blob(content, type); filename = filename || generateFilename(type); } var a = document.createElement("a"), href = URL.createObjectURL(textBlob); a.href = href; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(href); } function dataURL2Blob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); } function plain2Blob(text, type) { var fileTypes = { text: 'text/plain', svg: 'image/svg+xml', } return new Blob([text], { type: fileTypes[type] || 'application/octet-stream' }) } function generateFilename(type) { var prefixs = { text: 'txt', svg: 'svg', } return '1.' + (prefixs[type] || '.txt') } 复制代码
6.2 测试
// 下载txt文件 downloadFile(`测试\r\n第二行`, 'text',) // 下载svg downloadFile(`<svg version="1.1" id="tuceng_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="80px" height="36px" viewBox="0 0 80 36" enable-background="new 0 0 80 36" xml:space="preserve"> <rect y="34.129" fill="#009944" width="36" height="2"/> </svg>`, 'svg', '1.svg') // 下载图片 var data = 'data:image/png;base64,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 Go 2br+qXapWBdpVldq1OXFXua/801sZIIQBQhgghAFCGCC+spp01be1anKD2OLLJrcH9l3ngbvqrAwQwgAhDBDCACEMEDdnup3dAPWNm61W7rXxTLeavvneZzuRVqgmwZ8RBghhgBAGCGGAWKomTZoczlxra+nrg1q8eO12u76is+W+1sP7rAwQwgAhDBDCACEMEDfVJPh/sjJACAOEMEAIA4QwQAgDxD+aYuUyl4qrbgAAAABJRU5ErkJggg=='; downloadFile(data, 'img', '1.png') 复制代码
6.3 下载函数说明
目前只支持文本文件,svg,图片三种格式。
7 总结
Blob的作用还是蛮大的,在一定程度上可以在前端直接生成文件从而进行 上传或者下载 。
File 也是 继承自 Blob, 所以生成的 图片Blob 也是可以直接通过 ajax 上传 OSS 之类的进行存储。之前有一个项目其中一部分是 在线PPT,我就是用 Blob 上传 PPT的首图 到 OSS 的。
以上所述就是小编给大家介绍的《关于二进制的一点小思考》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。