2012-12-20 11 views
8

私はs3にイメージを保存するためにnode.jsを使用するイメージサーバーを作成しようとしています。画像をアップロードするとうまく動作し、s3ブラウザクライアントを使用して正しくダウンロードして表示できます(特に私はdragondiskを使用していますが、他のものとのダウンロードにも成功しました)。しかし、ノードでダウンロードして試してみるとそれをディスクに書き込むには、ファイルを開くことができません(ファイルが破損しているか、またはプレビューが認識できないファイル形式を使用している可能性があります)。私はnodeとfsにamazon sdkを使ってファイルを書いています。オプションのエンコーディングをfs.writeFileに渡すことができますが、それらをすべて試しても機能しません。また、getObjectのputObjectとResponseContentTypeのContentTypeと、ContentEncodingとResponseContentEncoding(およびこれらのすべてをさまざまな組み合わせで設定)を試みました。同じ結果。ここではいくつかのコードがあります:ちなみにs3に保存された画像をnode.jsを使って保存しますか?

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

私はちょうどことを発見fs.readFile()とfs.writeFile()へのエンコーディングとして 'base64'を渡すと、その逆が真です。私は自分のサービスを使ってイメージをダウンロードして見ることができますが、s3ブラウザクライアントを使ってイメージをダウンロードするとそれを見ることはできません。両方を行う方法はありますか? – tandrewnichols

答えて

5

[OK]を、かなりの試行錯誤の後、私はこれを行う方法を考え出した。私は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呼び出しでS3 Bodyに渡しているストリームに.lengthプロパティを設定すると、そのトリックが完了しているはずです。 –

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" 
} 
関連する問題