10

node.js を使用して s3 に画像を保存する画像サーバーを作成しようとしています。画像のアップロードは正常に機能し、s3ブラウザークライアントを使用して正しくダウンロードして表示できます(具体的にはdragondiskを使用していますが、他のものでも正常にダウンロードしました)が、ノードでダウンロードして試してみるとファイルをディスクに書き込むことができません (ファイルが破損しているか、Preview が認識しないファイル形式を使用している可能性があると表示されます)。ノードと fs に amazon sdk を使用してファイルを書き込みます。オプションのエンコーディングを fs.writeFile に渡すことができることは知っていますが、すべて試してみましたが、うまくいきません。また、putObject に ContentType を、getObject に ResponseContentType を、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}));
    });
};

ちなみに、私はルーティングに Express を使用しているので、req.params はそこから来ています。

4

4 に答える 4

6

さて、かなりの試行錯誤の末、私はこれを行う方法を理解しました。最終的に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()データチャンクをバッファとして返します。結果をフロントエンドに直接パイプすることができると思うかもしれませんが、何らかの理由で、これがサービスに画像を正しく返すことができる唯一の方法でした。バッファをバイナリ文字列に書き込んで、バッファに書き戻すのは冗長だと感じますが、機能する場合は機能します。誰かがより効率的な解決策を見つけたら、私はそれを聞いてみたいです。

于 2013-01-03T20:08:39.510 に答える
0

別の解決策として。代わりに Body: fs.createReadStream を使用して修正したところ、魅力的に機能しました。

 const uploadFile = () => {
fs.readFile(filename, (err, data) => {
  if (err) throw err;
  const params = {
    Bucket: `${process.env.S3_Bucket}/ProfilePics`, // pass your bucket name
    Key: `${decoded.id}-pic.${filetypeabbrv}`, // file will be saved as testBucket/contacts.csv
    Body: fs.createReadStream(req.file.path),
    ContentType: filetype,
  };

  s3.upload(params, function (s3Err, data) {
    if (s3Err) throw s3Err;
    console.log(`File uploaded successfully at ${data.Location}`);
  });
});

};

于 2020-09-07T02:10:20.427 に答える