从发送到 Node.js 服务器的请求主体中提取二进制数据(JPEG 图像)

7

需要解决的问题

你好。我收到了一个iPhone应用程序,它的功能之一是向服务器发送一个二进制jpeg图像请求。我需要找到一种方法来读取该二进制数据,通过socket.io将其发送给客户端,并将图像的副本记录到服务器上的磁盘。

第一次尝试:

我尝试了几种方法都没有成功。首先我尝试了这个:

var http = require('http');
var fs = require('fs');

http.createServer(function (req, res) {
console.log("Request In");
    var body = '';
    req.on('data', function (data) {
        body += data;
    });
    req.on('end', function () {
        fs.writeFile("./1.jpeg", body, function(err) {
        if(err) {
            console.log(err);
           } else {
            console.log("The file was saved!");
     }
});
    });
res.writeHead(200, {'Content-Type':'text/plain'});
res.end('Image Saved!');
}).listen(3000);
console.log('Server running at http://127.0.0.1:3000/');

这没行得通。我无法获取可在Windows照片查看器中打开的图像。Windows照片查看器给出了如下错误:Windows照片查看器无法打开此图片,因为照片查看器不支持此文件格式或您没有照片查看器的最新更新。我确定我有最新版本。接着我想知道问题是否出在手机和服务器之间。

检查请求准确性

我安装了Fiddler 2。我设置了一个反向代理,详见这里。我点击请求,然后转到十六进制视图。通过右键单击并选择保存字节,我将头信息后面的字节保存下来。我将文件命名为test.jpg,它可以在Windows照片查看器中正常打开。

saving bytes

我根据“头字节”和“正文字节”的不同颜色选择要保存的字节。

colored bytes

以下是我从保存这些字节得到的图像示例

enter image description here

第二次尝试:

既然我知道图像在请求中,也知道可以使用fiddler获取它,我在stackoverflow和谷歌上寻找如何捕获请求正文的方法。我尝试了很多解决方案,但是没有一个能给我一个可打开的图像。

//Express.js
var express = require('express');
var app = express();
var fs = require('fs');

app.configure(function(){
    app.use(express.bodyParser());
    app.use(function(req, res, next) {
        req.rawBody = '';
        // req.setEncoding('base64');
        req.setEncoding(null);
        req.on('data', function(chunk) { 
            req.rawBody += chunk;
        });
        req.on('end', function() {
            next();
        });
    });
});

app.listen(3000);

app.get('*', function(req, res){
    res.writeHead(200);
    res.end('Hello World');
    console.log(req.rawBody);
});

app.put('*',  function(req, res){
    console.log("putted");
    res.writeHead(200);
    res.end('Hello World');
    fs.writeFile("./1.jpg", req.rawBody, function(err) {
        if(err) {
            console.log(err);
        } else {
            console.log("The file was saved!");
        }
    });
    console.log(req.headers);
    console.log(req.params);
    console.log(req.body);
});
console.log("running");

据我所知,express bodyParser 寻找 json 键值对,因为请求正文只是一堆二进制数据,所以它返回一个空数组/对象(不确定哪个)。我编写了自定义中间件,根据 stackoverflow 上的这个答案 的建议,在请求对象 (req) 中添加了一个 rawBody 变量。有几篇文章说要使用 req.setEncoding('something') 让 Node.js 知道数据的编码方式。我尝试了 nullbase64hexbinary
如果您愿意看一下,我上传了从 Fiddler 2 保存的请求。 Fiddler 2 请求。注意: 我不知道要使用什么文件扩展名,所以没有使用任何文件扩展名。 我现在陷入了困境。 我尝试了谷歌和 stackoverflow 上能找到的所有解决方案。如果需要澄清,请提出问题。我尽可能详细地说明了问题(抱歉内容有点长)。感谢您花时间阅读到这里!

附注/额外信息

我不太了解 Node.js 缓冲区是如何工作的。如果可能的话,我希望能够接受这些图像的“流”。我不知道缓冲区可能会如何影响答案,但如果有,请尝试解释一下,假设我对缓冲区的了解很少。

我还提到想通过 socket.io 将图像发送到浏览器。如果您愿意在您的答案中包含这个第二部分,那将不胜感激。

如果您愿意,请包括您的解决方案的性能信息。(CPU 或内存占用情况等)

1个回答

4
这应该可以解决问题:
var http = require('http');
var fs = require('fs');

var app = http.createServer(function (req, res) {
  req.pipe(fs.createWriteStream(__dirname + req.url));

  res.writeHead(201);
  res.end();
});

app.listen(3000);

使用curl进行验证:

curl -H 'Content-Type: application/octet-stream' --data-binary @file.jpg localhost:3000/foo.jpg

如果这不起作用,我会用curl测试一下,确保不是客户端出了什么问题。
当涉及到通过socket.io发送它时,我不会这样做,而是发送URL。如果那不是一个选项,我想你应该使用base64编码数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接