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 Photo Viewer can't open this picture because either Photo Viewer doesn't support this file format, or you don't have the latest updates to Photo Viewer,我确定我有最新版本。接下来我想知道电话和服务器之间的请求是否混乱。

检查请求保真度

我安装了提琴手 2。我设置了一个反向代理,在此处详述。我单击了请求,然后转到了十六进制视图。我通过右键单击选择保存字节来保存标题信息之后的字节。我将文件命名为 test.jpg,它在 Windows Photo Viewer 中打开得很好。

节省字节

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

彩色字节

这是我最终通过保存这些字节获得的图像示例

在此处输入图像描述

第二次尝试:

现在我知道图像在请求中并且我知道我可以使用 fiddler,我搜索了 stackoverflow 和 google 以找到如何捕获请求正文。我尝试了一堆解决方案,但没有一个给我可以打开的图像。

//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 上的这个答案的建议,我编写了自定义中间件,将 rawBody 变量添加到请求对象 (req) 中。据说有几篇文章req.setEncoding('something')可以让 Node.js 知道数据是如何编码的。我试过null base64 hexbinary

我已经从 Fiddler 2 上传了保存的请求,如果你想看看的话。提琴手 2 请求注意:我不确定要使用什么文件扩展名,所以我没有使用任何文件扩展名。

我目前被卡住了。我已经尝试了所有可以在 google 和 stackoverflow 上找到的解决方案。如果您需要,请要求澄清。我试图尽可能详细(对不起,长度)。感谢您抽出宝贵时间阅读本文!

旁注/额外

我对 Node.js 缓冲区的工作了解不多。如果可能的话,我希望能够接受这些图像的“流”。我不知道缓冲区如何影响答案,但如果确实如此,请尝试解释它,假设我对缓冲区知之甚少。

我还提到希望通过 socket.io 将图像发送到浏览器。如果您想在答案中包含第二组,我们将不胜感激。

如果您愿意,请提供有关您的解决方案将如何执行的信息。(在 CPU 或内存上很重,或者在一个上很轻,等等)

4

1 回答 1

5

这应该这样做:

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对数据进行编码。

于 2013-10-28T12:50:16.210 回答