Node.js中request模块对Buffer的处理详解

我在工作过程中用到了request模块来模拟前端请求进行接口测试,但是在测试buffer的时候遇到了问题,卡了很久,查阅了大量的资料才发现是个由底层逻辑触发的乌龙。因此记录下来并分享给各位。

首先引入request模块(假设你已有NodeJS):

npm install -s request

同时你需要一个后端,可以使用express-generator生成,参考https://blog.csdn.net/Z_ammo/article/details/103559758

设置接口:

app = express();
app.post('/', function(req, res, next) {
  console.log(req.headers);
  let buf = [];
  req.on('data', (data) => {
    buf.push(data);
  });
  req.on('end', () => {
    buf = Buffer.concat(buf);
    console.log(buf.toString());
  });
  res.send('1');
});

现在发送请求:

var formData = {
  my_field: 'my_value',
  my_buffer: Buffer.from([1,2,3]) // 这里我使用了request官方的示例,也就是坑爹的开始
};

//post请求
request.post({
    url: "http://127.0.0.1:8080/",
    headers: {
        "content-type": "multipart/form-data",
    },
    formData: formData
}, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
});

好的,那么我们来看看后端收到的请求吧:

{
  'content-type': 'multipart/form-data; boundary=--------------------------536170949929771112772934',
  host: '127.0.0.1:3000',
  'content-length': '322',
  connection: 'close'
}
POST / 200 10.093 ms - 1
----------------------------536170949929771112772934
Content-Disposition: form-data; name="my_field"

my_value
----------------------------536170949929771112772934
Content-Disposition: form-data; name="my_buffer"
Content-Type: application/octet-stream


----------------------------536170949929771112772934--

结果是:字符串很正常的收到了,但是Buffer对象却没有显示出来(实际上显示了三个方框,也就是乱码)。

我以为是Buffer自动分块的问题,但是即便采用了Buffer拼接也无济于事,更何况这里使用的是ASCII码,没有分块问题。

我还怀疑是编码问题,但是不论怎么修改编码方式,结果都是乱码,不得已,只能从二进制数据入手了。

打印JSON.stringify()

console.log(JSON.stringify(buf));

结果如下:

{"type":"Buffer","data":[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,51,49,49,50,55,56,57,53,54,56,57,55,50,49,49,52,57,53,50,53,56,51,55,48,13,10,67,111,110,116,101,110,116,45,68,105,115,112,111,115,105,116,105,111,110,58,32,102,111,114,109,45,100,97,116,97,59,32,110,97,109,101,61,34,109,121,95,102,105,101,108,100,34,13,10,13,10,109,121,95,118,97,108,117,101,13,10,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,51,49,49,50,55,56,57,53,54,56,57,55,50,49,49,52,57,53,50,53,56,51,55,48,13,10,67,111,110,116,101,110,116,45,68,105,115,112,111,115,105,116,105,111,110,58,32,102,111,114,109,45,100,97,116,97,59,32,110,97,109,101,61,34,109,121,95,98,117,102,102,101,114,34,13,10,67,111,110,116,101,110,116,45,84,121,112,101,58,32,97,112,112,108,105,99,97,116,105,111,110,47,111,99,116,101,116,45,115,116,114,101,97,109,13,10,13,10,1,2,3,13,10,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,51,49,49,50,55,56,57,53,54,56,57,55,50,49,49,52,57,53,50,53,56,51,55,48,45,45,13,10]}

首先我们看到,数字中存在大量的'45'区间,很明显这就是我们的'--------------'分割符,因此可以确定大致区域。经过处理,我找到乱码的区域如下:

13,10,13,10,1,2,3,13,10

现在我们验证一下:

45:-    13:回车    10:换行    1:标题开始     2:正文开始    3:正文结束

所以Buffer的内容可以解释为:

“回车”“换行”“回车”“换行”“标题,文件正文,正文结束”“回车”“换行”

所以这个Buffer实际上是传递了一个空的文档!因为全是“无法描述”的字符,所以是乱码。

那么文件的主体在哪里呢?我的数组呢?

我查看了request的官方文档:https://www.npmjs.com/package/request

发现原来request的form-data处理是引用了外部的模块:https://github.com/form-data/form-data

来看看官方的示例:

var form = new FormData();
form.append( 'my_buffer', Buffer.from([0x4a,0x42,0x20,0x52,0x6f,0x63,0x6b,0x73]) );
form.append( 'my_file', fs.readFileSync('/foo/bar.jpg') );

axios.post( 'https://example.com/path/to/api',
            form.getBuffer(),
            form.getHeaders()
          )

官方也是简单地将数组转换成Buffer,而且没有乱码。

这里我才意识到,官方发送的是16进制数字,而我使用的示例发送的是1,2,3。

突然想起来,Buffer会将数组的内容转换为对应的编码,然后依次连接!

也就是说,“13,10,13,10,1,2,3,13,10”中的“1,2,3”实际上就是我们传递的数组参数,而不是什么文件内容!

我晕……

我是按照request官方文档的示例,使用了'[1,2,3]'的数组……

request官方文档使用的样例也太随意了……

另,form-data模块官方文档提示:不要直接传递Array对象,直接传递Array对象会自动拆分其内容,并分成多个数据块传递。

发布了19 篇原创文章 · 获赞 0 · 访问量 1453

猜你喜欢

转载自blog.csdn.net/Z_ammo/article/details/103684432