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

ang*_*inb 7 binary jpeg node.js express socket.io

要解决的问题

你好.我得到了一个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/');
Run Code Online (Sandbox Code Playgroud)

这没用.我无法获得可在Windows Photo Viewer中打开的图像.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我确定我有最新版本.我接下来想知道请求是否在手机和服务器之间搞砸了.

检查请求保真度

我安装了Fiddler 2.我设置一个反向代理,详细说明在这里.我点击了请求,然后转到了十六进制视图.我通过右键单击选择保存字节来保存标题信息后的字节.我将文件命名为test.jpg,它在Windows Photo Viewer中打开就好了.

保存字节

我根据"标题字节"和"正文字节"上的不同颜色选择保存哪些字节

彩色字节

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

在此输入图像描述

第二次尝试:

现在,我知道图像在请求中,我知道我可以使用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");
Run Code Online (Sandbox Code Playgroud)

据我所知,express bodyParser查找json键值对,因为请求体只是一堆二进制数据,它返回一个空数组/对象(不确定哪个).我编写了自定义中间件,它在stackoverflow上这个答案的建议中将rawBody变量添加到请求对象(req).一些文章说用来req.setEncoding('something')让Node.js知道数据是如何编码的.我试着null base64 hexbinary.

我已经上传了来自Fiddler 2的已保存的请求,如果您想查看一下.提琴手2请求.注意:我不确定要使用哪个文件扩展名,所以我没有使用任何文件扩展名.

我目前卡住了.我已经尝试了我可以在google和stackoverflow上找到的所有解决方案.如果需要,请询问澄清.我试图尽可能详细(抱歉长度).感谢您花时间阅读这篇文章!

旁注/额外

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

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

如果您愿意,请提供有关您的解决方案如何执行的信息.(重CPU或内存或亮灯等)

Lin*_*iel 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);
Run Code Online (Sandbox Code Playgroud)

已验证curl

curl -H 'Content-Type: application/octet-stream' --data-binary @file.jpg localhost:3000/foo.jpg
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,我会用curl 测试它,以确保不是客户端在做奇怪的事情。

当涉及到通过 socket.io 发送它时,我不会这样做,而是发送 URL。如果这不是一个选项,我想你将不得不对base64数据进行编码。