博主信息
博文 143
粉丝 1
评论 0
访问量 425545
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
Nodejs Buffer拼接
弘德誉曦的博客
原创
1701人浏览过

文章目录

  • 1 背景
  • 2 buffer拼接
  • 3 buffer 截取

1 背景

最近有一个需求需要将缩略图和视频文件合并到一起用HTTP POST 发送给服务器,服务器解析后拆成缩略图和视频文件存储到云存储中。

于是就写了下面这段代码读了读取两个文件,并相加。就实现下面这段代码。

  1. const fs = require('fs');
  2. const http = require('http');
  3. const thumbnail = fs.readFileSync('./20190306_00160734.jpg');
  4. const video = fs.readFileSync('./20190306_00160734.MOV');
  5. const bodyData = thumbnail + video;// thumbnail + video;
  6. console.info(`thumbnail length :${thumbnail.length}`);
  7. console.info(`video length :${video.length}`);
  8. console.info(`video+thumbnail length:${ video.length+thumbnail.length}`);
  9. console.info(`result length :${bodyData.length}`);
  10. 输出:
  11. thumbnail length :103143
  12. video length :1193998
  13. video+thumbnail length:1297141
  14. result length :1231302

结果发现两个buffer相加后的变量大小比两个变量大小的和更大, 黑人问号???
后面一想, fs.readFileSync 这东西读出来的东西应该不是string 。 这东西是一个buffer。
再一想, 依稀想到深入浅出nodejs里面说过buffer不能拿着就开加,而是有相应API(buffer.concat)去拼接。

而如果直接用这个去做 加法 会发生什么事呢?
Buffer1+Buffer2
两个buffer 相加实质上是两个buffer 转成string 相加。
Buffer1.toString()+Buffer2.toString()
而为什么toString会出现这个问题呢?实质上归根接地还是toString 编码的原因造成:
toString 行为默认编码是UTF-8格式。而readFile 默认是没有编码的。

  1. const fs = require('fs');
  2. const http = require('http');
  3. const thumbnail = fs.readFileSync('./20190306_00160734.jpg');
  4. const video = fs.readFileSync('./20190306_00160734.MOV');
  5. console.info(`thumbnail length :${thumbnail.length}`);
  6. console.info(`thumbnail string length:${thumbnail.toString().length}`);
  7. console.info(`video length :${video.length}`);
  8. console.info(`video string length :${video.toString().length}`);
  9. 输出
  10. thumbnail length :103143
  11. thumbnail string length:99410
  12. video length :1193998
  13. video string length :1131892

可以很明显看到 Buffer toString(对2进制数据UTF8编码后) 后length都发生了变化。数据长度变小了 。最终导致结果不对。

2 buffer拼接

Nodejs 提供了下面这个API 进行拼接

  1. Buffer.concat(list[, totalLength])
  2. list <Buffer[]> | <Uint8Array[]> 要合并的 Buffer 数组或 Uint8Array 数组。
  3. totalLength <integer> 合并后 list 中的 Buffer 实例的总长度。
  4. 返回: <Buffer>
  5. sample
  6. const buf1 = Buffer.alloc(10);
  7. const buf2 = Buffer.alloc(14);
  8. const buf3 = Buffer.alloc(18);
  9. const totalLength = buf1.length + buf2.length + buf3.length;
  10. console.log(totalLength);
  11. // Prints: 42
  12. const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
  13. console.log(bufA);
  14. // Prints: <Buffer 00 00 00 00 ...>
  15. console.log(bufA.length);
  16. // Prints: 42

使用上诉API,对缩略图和video文件进行拼接后数据大小就正常了。

  1. const fs = require('fs');
  2. const http = require('http');
  3. const thumbnail = fs.readFileSync('./20190306_00160734.jpg');
  4. const video = fs.readFileSync('./20190306_00160734.MOV');
  5. const bodyData1 = Buffer.concat([thumbnail, video], video.length+thumbnail.length);
  6. console.info(`thumbnail length :${thumbnail.length}`);
  7. console.info(`video length :${video.length}`);
  8. console.info(`thumbnail+video length:${thumbnail.length + video.length}`);
  9. console.info(`concat length :${bodyData1.length}`);
  10. 输出
  11. thumbnail length :103143
  12. video length :1193998
  13. thumbnail+video length:1297141
  14. concat length :1297141

3 buffer 截取

这里拼接成功后,发给服务器,服务器实质上也要进行buffer截取。提取出对应缩略图和video 调用的是下面的API:

  1. Buffer.from(arrayBuffer[, byteOffset[, length]])
  2. arrayBuffer <ArrayBuffer> | <SharedArrayBuffer> 一个 ArrayBufferSharedArrayBuffer、或 TypedArray .buffer 属性。
  3. byteOffset <integer> 开始拷贝的索引。默认值: 0
  4. length <integer> 拷贝的字节数。默认值: arrayBuffer.length - byteOffset
  5. const ab = new ArrayBuffer(10);
  6. const buf = Buffer.from(ab, 0, 2);
  7. console.log(buf.length);

实例

比如通过下面方式接受HTTP Body 中内容.
下面代码分段接受数据 通过,数组方式暂存各段数据,再使用concat 拼接数据。
这里比较关键的是Buffer.from(arrayBuffer[, byteOffset[, length]]) API 接受参数是arrayBuffer。
concat API 返回的是buffer, 所以这里要用 Buffer.buffer 把Buffer转换成ArrayBuffer。

  1. let trunks = [];
  2. let trunksLength = 0;
  3. req.on('data',function(trunk){
  4. trunks.push(trunk); //Data: video + thumbnail Size: video.length
  5. trunksLength+=trunk.length;
  6. }).on('end',function(){
  7. logger.info(trunksLength);
  8. const uploadFileData = Buffer.concat(trunks, trunksLength);
  9. const viodeBuffer = Buffer.from(uploadFileData.buffer, 0, req.headers.size);
  10. const thumbnailBuffer = Buffer.from(uploadFileData.buffer, req.headers.size);
  11. });
本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学