浅谈JS的二进制家族


Posted in Javascript onMay 09, 2021

概述

Blob: 前端的一个专门用于支持文件操作的二进制对象

ArrayBuffer:前端的一个通用的二进制缓冲区,类似数组,但在API和特性上却有诸多不同

Buffer:Node.js提供的一个二进制缓冲区,常用来处理I/O操作

Blob

我们首先来介绍Blob,Blob是用来支持文件操作的。简单的说:在JS中,有两个构造函数 File 和 Blob, 而File继承了所有Blob的属性。

所以在我们看来,File对象可以看作一种特殊的Blob对象。

在前端工程中,我们在哪些操作中可以获得File对象呢? 请看:

浅谈JS的二进制家族

(备注:目前 File API规范的状态为Working Draft)

我们上面说了,File对象是一种特殊的Blob对象,那么它自然就可以直接调用Blob对象的方法。让我们看一看Blob具体有哪些方法,以及能够用它们实现哪些功能

浅谈JS的二进制家族

Blob实战

通过window.URL.createObjectURL方法可以把一个blob转化为一个Blob URL,并且用做文件下载或者图片显示的链接。

Blob URL所实现的下载或者显示等功能,仅仅可以在单个浏览器内部进行。而不能在服务器上进行存储,亦或者说它没有在服务器端存储的意义。

下面是一个Blob的例子,可以看到它很短

blob:d3958f5c-0777-0845-9dcf-2cb28783acaf

和冗长的Base64格式的Data URL相比,Blob URL的长度显然不能够存储足够的信息,这也就意味着它只是类似于一个浏览器内部的“引用“。从这个角度看,Blob URL是一个浏览器自行制定的一个伪协议

Blob下载文件

我们可以通过window.URL.createObjectURL,接收一个Blob(File)对象,将其转化为Blob URL,然后赋给 a.download属性,然后在页面上点击这个链接就可以实现下载了

<!-- html部分 -->
<a id="h">点此进行下载</a>
<!-- js部分 -->
<script>
  var blob = new Blob(["Hello World"]);
  var url = window.URL.createObjectURL(blob);
  var a = document.getElementById("h");
  a.download = "helloworld.txt";
  a.href = url;
</script>

备注:download属性不兼容IE, 对IE可通过window.navigator.msSaveBlob方法或其他进行优化(IE10/11)

运行结果

浅谈JS的二进制家族

Blob图片本地显示

window.URL.createObjectURL生成的Blob URL还可以赋给img.src,从而实现图片的显示

<!-- html部分 -->
<input type="file" id='f' />
<img id='img' style="width: 200px;height:200px;" />
<!-- js部分 -->
<script>
  document.getElementById('f').addEventListener('change', function (e) {
    var file = this.files[0];
    const img = document.getElementById('img');
    const url = window.URL.createObjectURL(file);
    img.src = url;
    img.onload = function () {
        // 释放一个之前通过调用 URL.createObjectURL创建的 URL 对象
        window.URL.revokeObjectURL(url);
    }
  }, false);
</script>

运行结果

浅谈JS的二进制家族

Blob文件分片上传

  • 通过Blob.slice(start,end)可以分割大Blob为多个小Blob
  • xhr.send是可以直接发送Blob对象的

前端

<!-- html部分 -->
<input type="file" id='f' />
<!-- js部分 -->
<script>
  function upload(blob) {
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/ajax', true);
    xhr.setRequestHeader('Content-Type', 'text/plain')
    xhr.send(blob);
  }
  document.getElementById('f').addEventListener('change', function (e) {
    var blob = this.files[0];
    const CHUNK_SIZE = 20; .
    const SIZE = blob.size;
    var start = 0;
    var end = CHUNK_SIZE;
    while (start < SIZE) {
        upload(blob.slice(start, end));
        start = end;
        end = start + CHUNK_SIZE;
    }
  }, false);
</script>

Node端

app.use(async (ctx, next) => {
    await next();
    if (ctx.path === '/ajax') {
        const req = ctx.req;
        const body = await parse(req);
        ctx.status = 200;
        console.log(body);
        console.log('---------------');
    }
});

文件内容

According to the Zhanjiang commerce bureau, the actual amount of foreign capital utilized in Zhanjiang from January to October this year was

运行结果

浅谈JS的二进制家族

本地读取文件内容

如果想要读取Blob或者文件对象并转化为其他格式的数据,可以借助FileReader对象的API进行操作

  • FileReader.readAsText(Blob):将Blob转化为文本字符串
  • FileReader.readAsArrayBuffer(Blob): 将Blob转为ArrayBuffer格式数据
  • FileReader.readAsDataURL(): 将Blob转化为Base64格式的Data URL

下面我们尝试把一个文件的内容通过字符串的方式读取出来

<input type="file" id='f' />


document.getElementById('f').addEventListener('change', function (e) {
    var file = this.files[0];
    const reader = new FileReader();
    reader.onload = function () {
        const content = reader.result;
        console.log(content);
    }
    reader.readAsText(file);
}, false);

运行结果

浅谈JS的二进制家族

上面介绍了Blob的用法,我们不难发现,Blob是针对文件的,或者可以说它就是一个文件对象,同时呢我们发现Blob欠缺对二进制数据的细节操作能力,比如如果如果要具体修改某一部分的二进制数据,Blob显然就不够用了,而这种细粒度的功能则可以由下面介绍的ArrayBuffer来完成。

ArrayBuffer

让我们用一张图看下ArrayBuffer的大体的功能

浅谈JS的二进制家族

同时要说明,ArrayBuffer跟JS的原生数组有很大的区别,如图所示

浅谈JS的二进制家族

下面一一进行细节的介绍

通过ArrayBuffer的格式读取本地数据

document.getElementById('f').addEventListener('change', function (e) {
  const file = this.files[0];
  const fileReader = new FileReader();
  fileReader.onload = function () {
    const result = fileReader.result;
    console.log(result)
  }
  fileReader.readAsArrayBuffer(file);
}, false);

运行结果

浅谈JS的二进制家族

通过ArrayBuffer的格式读取Ajax请求数据

通过xhr.responseType = "arraybuffer" 指定响应的数据类型

在onload回调里打印xhr.response

前端

const xhr = new XMLHttpRequest();
xhr.open("GET", "ajax", true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
    console.log(xhr.response)
}
xhr.send();

Node端

const app = new Koa();
app.use(async (ctx) => {
  if (pathname = '/ajax') {
        ctx.body = 'hello world';
        ctx.status = 200;
   }
}).listen(3000)

运行结果

浅谈JS的二进制家族

通过TypeArray对ArrayBuffer进行写操作

const typedArray1 = new Int8Array(8);
typedArray1[0] = 32;

const typedArray2 = new Int8Array(typedArray1);
typedArray2[1] = 42;
 
console.log(typedArray1);
//  output: Int8Array [32, 0, 0, 0, 0, 0, 0, 0]
 
console.log(typedArray2);
//  output: Int8Array [32, 42, 0, 0, 0, 0, 0, 0]

通过DataView对ArrayBuffer进行写操作

const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
view.setInt8(2, 42);
console.log(view.getInt8(2));
// 输出: 42

Buffer

Buffer是Node.js提供的对象,前端没有。 它一般应用于IO操作,例如接收前端请求数据时候,可以通过以下的Buffer的API对接收到的前端数据进行整合

浅谈JS的二进制家族

Buffer实战

例子如下:

Node端(Koa)

const app = new Koa();
app.use(async (ctx, next) => {
    if (ctx.path === '/ajax') {
        const chunks = [];
        const req = ctx.req;
        req.on('data', buf => {
            chunks.push(buf);
        })
        req.on('end', () => {
            let buffer = Buffer.concat(chunks);
            console.log(buffer.toString())
        })
    }
});
app.listen(3000)

前端

const xhr = new XMLHttpRequest();
xhr.open("POST", "ajax", true);
xhr.setRequestHeader('Content-Type', 'text/plain')
xhr.send("asdasdsadfsdfsadasdas");

运行结果

Node端输出

asdasdsadfsdfsadasdas

以上就是浅谈JS的二进制家族的详细内容,更多关于JS的二进制家族的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
利用js 进行输入框自动匹配字符的小例子
Jun 29 Javascript
关于IE中getElementsByClassName不能用的问题解决方法
Aug 26 Javascript
js通过元素class名字获取元素集合的具体实现
Jan 06 Javascript
让table变成exls的示例代码
Mar 24 Javascript
JavaScript保留关键字汇总
Dec 01 Javascript
js原生实现FastClick事件的实例
Nov 20 Javascript
Javascript前端经典的面试题及答案
Mar 14 Javascript
JavaScript编写的网页小游戏,很给力
Aug 18 Javascript
Vue组件实例间的直接访问实现代码
Aug 20 Javascript
小程序实现授权登陆的解决方案
Dec 02 Javascript
JS中的算法与数据结构之链表(Linked-list)实例详解
Aug 20 Javascript
JS如何生成动态列表
Sep 22 Javascript
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
详解JS ES6编码规范
May 07 #Javascript
You might like
PHP的Socket通信之UDP通信实例
2015/07/02 PHP
变量在 PHP7 内部的实现(二)
2015/12/21 PHP
开启PHP的伪静态模式
2015/12/31 PHP
PHP使用curl_multi_select解决curl_multi网页假死问题的方法
2018/08/15 PHP
微信公众平台开发教程②微信端分享功能图文详解
2019/04/10 PHP
PHP利用百度ai实现文本和图片审核
2019/05/08 PHP
js 获取、清空input type=&quot;file&quot;的值示例代码
2014/02/19 Javascript
JQuery选中checkbox方法代码实例(全选、反选、全不选)
2015/04/27 Javascript
JavaScript实现鼠标点击后层展开效果的方法
2015/05/13 Javascript
js实现鼠标点击左上角滑动菜单效果代码
2015/09/06 Javascript
JavaScript操作class和style样式代码详解
2016/02/13 Javascript
详解NodeJs支付宝移动支付签名及验签
2017/01/06 NodeJs
js弹出窗口简单实现代码
2017/03/22 Javascript
利用vue+elementUI实现部分引入组件的方法详解
2017/11/22 Javascript
禁止弹窗中蒙层底部页面跟随滚动的几种方法
2017/12/07 Javascript
electron-vue开发环境内存泄漏问题汇总
2019/10/10 Javascript
VuePress 中如何增加用户登录功能
2019/11/29 Javascript
详细分析vue响应式原理
2020/06/22 Javascript
[02:26]2018DOTA2亚洲邀请赛赛前采访-Newbee篇
2018/04/03 DOTA
使用Python编写一个简单的tic-tac-toe游戏的教程
2015/04/16 Python
Python迭代器定义与简单用法分析
2018/04/30 Python
flask框架中勾子函数的使用详解
2018/08/01 Python
Python 调用 Outlook 发送邮件过程解析
2019/08/08 Python
python tkinter基本属性详解
2019/09/16 Python
使用Python给头像戴上圣诞帽的图像操作过程解析
2019/09/20 Python
Python 私有化操作实例分析
2019/11/21 Python
Python实现将蓝底照片转化为白底照片功能完整实例
2019/12/13 Python
html5 localStorage本地存储_动力节点Java学院整理
2017/07/06 HTML / CSS
HTML5 Canvas的事件处理介绍
2015/04/24 HTML / CSS
Burberry英国官网:英国标志性奢侈品牌
2017/03/29 全球购物
家庭户外服装:Hawkshead
2017/11/02 全球购物
英国乐购杂货:Tesco Groceries
2018/11/29 全球购物
2014村党支部书记党建工作汇报材料
2014/11/02 职场文书
走群众路线学习笔记
2014/11/06 职场文书
郭明义观后感
2015/06/08 职场文书
微软Win11 全新照片应用面向 Dev预览版推出 新版本上手体验图集
2022/09/23 数码科技