使用node.js保存存储在s3上的图像?

我正在尝试编写一个使用node.js在s3上存储图像的图像服务器。 上传图片效果很好,我可以使用s3浏览器客户端(我使用的是dragondisk,但是我也成功下载了它)也可以正确下载和查看它,但是当我用节点下载并尝试将其写入磁盘,我无法打开该文件(它表示可能已损坏或使用预览无法识别的文件格式)。 我正在使用amazon sdk节点和fs写入文件。 我知道你可以通过一个可选的编码fs.writeFile,但我已经尝试了所有,它不起作用。 我也尝试在getObject上设置putObject和ResponseContentType上的ContentType,以及ContentEncoding和ResponseContentEncoding(以及各种组合中的所有这些东西)。 同样的结果。 这是一些代码:

var AWS = require('aws-sdk') , gm = require('../lib/gm') , uuid = require('node-uui') , fs = require('fs'); AWS.config.loadFromPath('./amazonConfig.json'); var s3 = new AWS.S3(); var bucket = 'myBucketName'; // There's other logic here to set the bucket name. exports.upload = function(req, res) { var id = uuid.v4(); gm.format("/path/to/some/image.jpg", function(format){ var key = req.params.dir + "/" + id + "/default." + format; fs.readFile('/path/to/some/image.jpg', function(err, data){ if (err) { console.warn(err); } else { s3.client.putObject({ Bucket: bucket, Key: key, Body: data, ContentType: 'image/jpeg' // I've also tried adding ContentEncoding (in various formats) here. }).done(function(response){ res.status(200).end(JSON.stringify({ok:1, id: id})); }).fail(function(response){ res.status(response.httpResponse.statusCode).end(JSON.stringify(({err: response}))); }); } }); }); }; exports.get = function(req, res) { var key = req.params.dir + "/" + req.params.id + "/default.JPEG"; s3.client.getObject({ Bucket: bucket, Key: key, ResponseContentType: 'image/jpeg' // Tried ResponseContentEncoding here in base64, binary, and utf8 }).done(function(response){ res.status(200).end(JSON.stringify({ok:1, response: response})); var filename = '/path/to/new/image/default.JPEG'; fs.writeFile(filename, response.data.Body, function(err){ if (err) console.warn(err); // This DOES write the file, just not as an image that can be opened. // I've tried pretty much every encoding as the optional third parameter // and I've matched the encodings to the ResponseContentEncoding and // ContentEncoding above (in case it needs to be the same) }); }).fail(function(response){ res.status(response.httpResponse.statusCode).end(JSON.stringify({err: response})); }); }; 

顺便说一句,我使用快递路由,所以这是req.params来自哪里。

对于那些仍在为这个问题而苦苦挣扎的人 这里是我用原生aws-sdk的方法。

 var AWS = require('aws-sdk'); AWS.config.loadFromPath('./s3_config.json'); var s3Bucket = new AWS.S3( { params: {Bucket: 'myBucket'} } ); 

在您的路由器方法内: – ContentType应该被设置为图像文件的内容types

  buf = new Buffer(req.body.imageBinary.replace(/^data:image\/\w+;base64,/, ""),'base64') var data = { Key: req.body.userId, Body: buf, ContentEncoding: 'base64', ContentType: 'image/jpeg' }; s3Bucket.putObject(data, function(err, data){ if (err) { console.log(err); console.log('Error uploading data: ', data); } else { console.log('succesfully uploaded the image!'); } }); 

s3_config.json文件是: –

 { "accessKeyId":"xxxxxxxxxxxxxxxx", "secretAccessKey":"xxxxxxxxxxxxxx", "region":"us-east-1" } 

好吧,经过重大的试验和错误,我已经想出了如何做到这一点。 我结束了切换到knox,但大概你可以使用aws-sdk类似的策略。 这就是让我说“必须有更好的办法”的解决方法,但是我现在对任何有效的方法都感到满意。

 var imgData = ""; client.getFile(key, function(err, fileRes){ fileRes.on('data', function(chunk){ imgData += chunk.toString('binary'); }).on('end', function(){ res.set('Content-Type', pic.mime); res.set('Content-Length', fileRes.headers['content-length']); res.send(new Buffer(imgData, 'binary')); }); }); 

getFile()返回数据块作为缓冲区。 人们会认为你可以把结果直接输出到前端,但无论出于何种原因,这是唯一可以让服务正确返回图像的方法。 把一个缓冲区写入一个二进制string感觉是多余的,只是把它写回到一个缓冲区中,但是,如果它能工作的话,它就可以工作。 如果有人find更有效的解决scheme,我很乐意听到它。