本文详解在 Node.js 的 httpServer 中如何正确接收前端发送的 ArrayBuffer 二进制数据。针对 protobuf 交互中常见的数据错乱问题,指出需在 req.on('data') 事件中累积数据块,并在 req.on('end') 中使用 Buffer.concat 合并数组以生成完整 Buffer。文章提供了 Node.js 后端接收代码及 Three.js 前端发送点阵和图片 Buffer 的完整示例,确保二进制数据传输的准确性。
Node.js 接收二进制数据的问题背景
近期在使用 protobuf 进行数据交互时,发现 Node.js 接收前端发送的二进制数据时出现了数据错误等问题。经过排查,发现根本原因在于代码逻辑处理不当,特别是在 req.on('data', () => {}) 事件中的处理方式引发了数据错乱。借此机会分享正确的处理思路与代码。
Node.js 接收 ArrayBuffer 的正确代码
首先直接展示接收二进制数据的正确代码实现。
const server = http.createServer((req, res) => {
if(req.method==='OPTIONS'){
res.setHeader("Access-Control-Allow-Origin", "*");
res.statusCode=200;
}
if(req.method==='POST'){
// 存储数组空间
let msg=[];
// 接收到数据消息
req.on('data',(chunk)=>{
if(chunk){
msg.push(chunk);
}
})
// 接收完毕
req.on('end',()=>{
// 对buffer数组阵列列表进行buffer合并返回一个Buffer
let buf=Buffer.concat(msg);
conosole.log(buf)//提取Buffer正确
})
}
});
server.listen(3000,'127.0.0.1');
在 Node.js 中接收 buffer 数据时,需要以数组阵列的方式存储接收到的数据块,然后通过 Buffer.concat 对数组阵列进行合并,从而创建新的 ArrayBuffer(或 Buffer 对象)。这样即可正确接收并处理二进制数据。
Three.js 点阵数组传输示例
以下是具体的代码示例二:
以下以从后端传送 Three.js 中的点阵数组为例进行说明:
后端 Node.js 代码实现如下:
let buffer = Buffer.alloc((points.length + 4) * 4)
//points.length + 4:预留前四个数字为其他信息(比如两个数字为一组,或者三个数字为一组)
//预留位置
buffer.writeFloatLE(1, 0)
buffer.writeFloatLE(2, 4)
buffer.writeFloatLE(3, 8)
buffer.writeFloatLE(4, 12)
//buffer前四个数为信息
//point数据从第16位开始写入
for (let i = 0, len = points.length; i < len; i++) {
buffer.writeFloatLE(points[i], i * 4 + 16)
}
res.send(buffer)
前端 JavaScript 代码实现如下:
let pointXhr = new XMLHttpRequest()
pointXhr.onreadystatechange = function () {
var DONE = pointXhr.DONE || 4;
if (pointXhr.readyState === DONE) {
let buffer = pointXhr.response
let bufferArray = new Float32Array(buffer);
for (var i = 0; i < buffer.length; ++i) {
bufferArray[i] = buffer[i];
}
let pointsArray = bufferArray.slice(4)
let points = []
//pointsArray 点阵从第5个开始(前四个数为其他信息)
for (let i = 0, l = pointsArray.length / 3; i < l; i++) {
points.push({
x: pointsArray[i * 3],
y: pointsArray[i * 3 + 1],
z: pointsArray[i * 3 + 2]
})
}
callback(points)
}
}
pointXhr.open("POST",url,true);
pointXhr.responseType = 'arraybuffer';
pointXhr.send(null);
前端接收图片 Buffer 示例
此外,前端接收图片 Buffer 的方法也类似,具体代码如下:
let imageXhr = new XMLHttpRequest()
imageXhr.onreadystatechange = function () {
var DONE = imageXhr.DONE || 4;
if (imageXhr.readyState === DONE) {
if (imageXhr.response) {
let bufferArray = imageXhr.response
let uint8Array = new Uint8Array(bufferArray);
for (var i = 0; i < bufferArray.length; ++i) {
uint8Array[i] = bufferArray[i];
}
callback(uint8Array)
}
}
}
imageXhr.open("POST",url,true);
imageXhr.responseType = 'arraybuffer';
imageXhr.send(null);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。