2012-12-20 40 views
8

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

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从何而来。

+0

我刚刚发现,如果我将'base64'作为编码传递给fs.readFile()和fs.writeFile(),则情况正好相反。我可以使用我的服务下载并查看图像,但如果使用s3浏览器客户端下载,则无法查看它。有两种做法吗? – tandrewnichols

回答

5

好吧,经过重大的试验和错误,我已经想出了如何做到这一点。我最终转而使用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()将数据块作为缓冲区返回。人们会认为你可以直接将结果输出到前端,但无论出于何种原因,这是我可以使服务正确返回图像的唯一方式。将一个缓冲区写入一个二进制字符串感觉有点多余,只能将它写回缓冲区,但是,如果它有效,它就会起作用。如果有人找到更有效的解决方案,我很乐意听到它。

+0

S3预计流的长度。也就是说,这是一种破解,但如果你在putObject调用中将流的.length属性设置为S3 Body,那就完成了这个任务。 –

10

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

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

路由器方法内: - 的ContentType应设置为内容类型的图像文件

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" 
} 
相关问题