POST 中的 nodejs/express 和二进制数据

Posted

技术标签:

【中文标题】POST 中的 nodejs/express 和二进制数据【英文标题】:nodejs/express and binary data in POST 【发布时间】:2013-12-28 11:55:12 【问题描述】:

我正在尝试将二进制数据发送到快速应用程序。只要我的值小于 0x80,它就可以正常工作。如果单个值是 0x80 或更大,它会弄乱整个缓冲区。

快递处理程序:

binary = require('binary');

exports.api = function(req, res)
    var body = req.body.name;
    var buf = new Buffer(body,'binary');

    console.log('body',req.body);
    console.log('req body len', body.length);
    console.log('buf len', buf.length);

    var g = binary.parse(buf)
        .word16bu('a') // unsigned 16-bit big-endian value
        .word16bu('b').vars

    console.log('g.a', g.a);
    console.log('g.b', g.b);

  res.send("respond with a resource");
;

Python 客户端(内容类型:application/x-www-form-urlencoded):

import requests
from struct import pack
# send two unsigned shorts (16-bits each).
requests.post('http://localhost:3000/api', data='name':pack('!HH',1,2))

当数据 = 1,2 时表示输出。 这是我所期望的

body  name: '\u0000\u0001\u0000\u0002' 
req body len 4
buf len 4
g.a 1
g.b 2
POST /api 200 1ms - 23b

当数据 = 1,0xFF 时表示输出。有趣的是,9520实际上是十六进制的0x25 0x30,对应ASCII中的“%0”。是的,它似乎正在解析 '%00%01...' 字符串。 我希望我知道如何防止这种情况发生!!!

body  name: '%00%01%00%FF' 
req body len 12
buf len 12
g.a 9520
g.b 12325
POST /api 200 2ms - 23b

【问题讨论】:

【参考方案1】:

在为此苦苦挣扎了太久之后,我想出了这个解决方案:

var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var path = require('path');

app.use(bodyParser.raw(type: 'application/octet-stream', limit : '2mb'))

app.post('/nist-ws/rest/v1/nist/', function(req, res) 
    var filePath = path.join(__dirname, 'nist_received', `/$Date.now().nist`)
    fs.open(filePath, 'w', function(err, fd)   
        fs.write(fd, req.body, 0, req.body.length, null, function(err) 
            if (err) throw 'error writing file: ' + err;
            fs.close(fd, function() 
                console.log('wrote the file successfully');
                res.status(200).end();
            );
        );
    );
);

bodyParser.raw 用 Buffer 填充 req.body,其余代码来自:https://stackabuse.com/writing-to-files-in-node-js/

【讨论】:

补充卡尔的答案。通过表单接收文件时,这对我不起作用。为了解决这个问题,我将他的bodyParser.raw 行更改为:app.use(bodyParser.raw(type: 'multipart/form-data', limit : '2mb')) 因为这是发送表单时的Content-Type【参考方案2】:

原来是编码问题。一切似乎都默认为“utf8”,但在这种情况下,它需要设置为“二进制”。

例如:

var buf = new Buffer(body.toString('binary'),'binary');

同样重要的是,我需要将 nodejs 多方解析器的编码设置为“二进制”。见:https://github.com/superjoe30/node-multiparty/issues/37

【讨论】:

我收到错误“req.body.toString 不是函数”,即使我声明 body 的方式与您相同。你知道这可能来自哪里吗?【参考方案3】:

现代的 Typescript 安全方式可能如下所示:

export async function readBodyAsBuffer(req: any): Promise<Buffer> 
  return new Promise((resolve, reject) => 
    let buffer = Buffer.alloc(0)
    req.setEncoding(null)
    req.on(
      "data",
      (chunk: string) => (buffer = Buffer.concat([buffer, Buffer.from(chunk)]))
    )
    req.on("end", () => resolve(buffer))
    req.on("error", reject)
  )

您现在可以像这样简单地将主体作为 Buffer 获取:

let buffer = await readBodyAsBuffer(req)

【讨论】:

以上是关于POST 中的 nodejs/express 和二进制数据的主要内容,如果未能解决你的问题,请参考以下文章

Nodejs + express post get 参数获取小结

Nodejs,Express + Angular POST 404

Nodejs express 获取url参数,post参数的三种方式

NodeJS Express - 幕后GET / POST / PATCH / DELETE之间的区别

为啥nodejs express服务器在我使用post时返回302?

nodejs express怎么获取到前端以post请求的Ajax请求信息,请求信息是JSON对象