节点 – 上传的jpg无法在服务器上打开

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

以下是更新后的服务器代码,其中包含一些来自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”无法打开。 它可能被损坏或使用预览无法识别的文件格式。

一些背景:

  • 一切(服务器,存储)都在本地托pipe
  • 由于微控制器板上的存储限制,决定只使用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上的编码设置为二进制,我也会得到类似的结果。

我究竟做错了什么? 谢谢!

客户端以multipart/form-data格式上传,这是一种可以包含文件数据的格式。

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

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提取文件数据并将其写入文件。