【问题标题】:Node - Uploaded jpg cannot be opened on server节点 - 无法在服务器上打开上传的 jpg
【发布时间】:2017-08-23 05:36:04
【问题描述】:

更新 感谢@robertklep 和@vallo 指出我没有正确解析多部分请求。

这是更新后的服务器代码,其中包含来自Busboy 的一些重新设计的示例代码:

'use strict';

// Require
var http    = require('http');
var Busboy  = require('busboy');
var fs      = require('fs');

// Server
var server = http.createServer(function(request, response) {
  if (request.method === 'POST') {
    var busboy = new Busboy({ headers: request.headers });
    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
      file.pipe(fs.createWriteStream(`../db/images/${filename}`));
    });
    busboy.on('finish', function() {
      response.writeHead(200, { 'Connection': 'close' });
      response.end("That's all folks!");
    });
    return request.pipe(busboy);
  }
  response.writeHead(404);
  response.end();
});
server.listen(8000, '192.168.7.25', () => {});

我正在尝试将 jpg 文件发布到端点,但生成的图像无法打开:

无法打开文件“image_copy.jpg”。它可能已损坏或 使用 Preview 无法识别的文件格式。

一些背景:

  • 一切(服务器、存储)都在本地托管
  • 由于微控制器板上的存储限制,已决定仅使用本地 Node 模块,例如 http 和 fs
  • 我正在使用表单数据,因为它减轻了多部分表单和上传的痛苦,并设置了正确的请求标头

下面是一些分成两个脚本的示例代码:

服务器

'use strict';

// Require
var http = require('http');

// Server
var server = http.createServer((request, response) => {
    var body = [];
    request.on('data', function(chunk) {
      body.push(chunk);
    });
    request.on('end', function() {
        saveImage(Buffer.concat(body),null);
        response.statusCode = 200;
        response.end('thanks')
    });
});
server.listen(8000, '192.168.7.25', () => {});


// Process
function saveImage(data,callback) {
    var fs = require('fs');
  fs.writeFile('../db/images/image_copy.jpg', data, function(err) {});
}

客户

'use strict';

// Require
var FormData    = require('form-data');
var fs          = require('fs');
var http        = require('http');

// Vars
var form = new FormData();

// Process
form.append('my_file', fs.createReadStream('/temp/1.jpg'));
var request = http.request({
  hostname: '192.168.7.25',
  port: 8000,
  path: '/api/premises/v1/image',
  method: 'POST',
  headers: form.getHeaders()
});
form.pipe(request);
request.on('response', function(res) {
  console.log(res.statusCode);
});

执行后,将jpg上传并保存到正确的文件位置(并且文件大小与源jpg相同)但无法打开新图像。

即使我将传入的块编码为二进制并将 fs.writeFile 上的编码设置为二进制,我也会得到类似的结果。

我做错了什么?谢谢!

【问题讨论】:

  • 您确定两个文件不同吗?您可以对它们进行哈希比较,或使用程序检查逐字节的差异
  • 您可以尝试发送一些更简单的内容,比如一个 .txt 文件,然后在从客户端发送之前在控制台上打印,并在服务器上收到它时打印相同的内容。这样你就可以调试发生了什么
  • @vallo 我确信源 jpg 是一个工作 jpg 并且没有损坏。在这一点上,我不想比较图像。我只是希望上传的图像能够正确编码/不损坏。
  • 如果您比较图像(或用文本文件对其进行测试),您会发现您在正文中添加了额外的信息,因此将其保存为 .jpg。不知道如何解决它,但你现在有一个线索。我的原始文本文件上只有“asd”,这就是服务器端 txt 文件的样子:imgur.com/LmjB0j6
  • @vallo 是的,我看到文件仍然具有处置标题和边界的位置。现在我需要研究如何正确解析缓冲区中的多部分/表单数据。感谢您的建议。

标签: node.js jpeg fs


【解决方案1】:

客户端正在以multipart/form-data 格式上传,该格式可以包含文件数据等。

但是,这意味着服务器应该解析这种格式来提取文件数据。现在,服务器只是逐字获取请求正文并将其写入文件。

multiparty 模块可以帮助您,其中一个使用示例向您展示了如何将其与http.Server 挂钩:https://github.com/pillarjs/multiparty#usage

var multiparty = require('multiparty');
var http = require('http');
var util = require('util');

http.createServer(function(req, res) {
  // parse a file upload
  var form = new multiparty.Form();

  form.parse(req, function(err, fields, files) {
    res.writeHead(200, {'content-type': 'text/plain'});
    res.write('received upload:\n\n');
    res.end(util.inspect({fields: fields, files: files}));
  });

}).listen(8000);

使用它,您可以从(我认为)files.my_file 提取文件数据并将其写入文件。

【讨论】:

  • 感谢您确认正确解析多部分请求的额外步骤。在顶部添加更新。谢谢!
猜你喜欢
  • 2019-11-26
  • 2016-12-10
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多