web-dev-qa-db-ja.com

NodeJS aws s3バケットからディスクにファイルをダウンロードするにはどうすればよいですか?

私の目標:

Awsからダウンロードするファイルを保存するようユーザーに促すダイアログボックスを表示します。

私の問題:

現在、ダウンロードストリームを作成するためにawssum-Amazon-s3を使用しています。しかし、ファイルをサーバーに保存するか、コマンドラインにストリームすることしかできませんでした...私のコードからわかるように、最後の試みは失敗したコンテンツ処理ヘッダーを手動で設定することでした。ヘッダーが既に設定されているため、res.download()を使用できませんか?

どうすれば目標を達成できますか?

ノードの私のコード:

app.post('/dls/:dlKey', function(req, res, next){
        // download the file via aws s3 here
        var dlKey = req.param('dlKey');

        Dl.findOne({key:dlKey}, function(err, dl){
            if (err) return next(err);
            var files = dl.dlFile;

            var options = {
                BucketName    : 'xxxx',
                ObjectName    : files,
            };

            s3.GetObject(options, { stream : true }, function(err, data) {
                // stream this file to stdout
                fmt.sep();
                data.Headers['Content-Disposition'] = 'attachment';
                console.log(data.Headers);
                data.Stream.pipe(fs.createWriteStream('test.pdf'));
                data.Stream.on('end', function() {
                    console.log('File Downloaded!');
                });
            });
        });

        res.end('Successful Download Post!');
    });

角度の私のコード:

$scope.dlComplete = function (dl) {
        $scope.procDownload = true;
        $http({
            method: 'POST',
            url: '/dls/' + dl.dlKey
        }).success(function(data/*, status, headers, config*/) {
            console.log(data);
            $location.path('/#!/success');
        }).error(function(/*data, status, headers, config*/) {
            console.log('File download failed!');
        });
    };

このコードの目的は、ユーザーが生成されたキーを使用してファイルを1回ダウンロードできるようにすることです。

28
gbachik

これは、最新バージョンのaws-sdkでストリーミングを使用するコード全体です。

var express = require('express');
var app = express();
var fs = require('fs');

app.get('/', function(req, res, next){
    res.send('You did not say the magic Word');
});


app.get('/s3Proxy', function(req, res, next){
    // download the file via aws s3 here
    var fileKey = req.query['fileKey'];

    console.log('Trying to download file', fileKey);
    var AWS = require('aws-sdk');
    AWS.config.update(
      {
        accessKeyId: "....",
        secretAccessKey: "...",
        region: 'ap-southeast-1'
      }
    );
    var s3 = new AWS.S3();
    var options = {
        Bucket    : '/bucket-url',
        Key    : fileKey,
    };

    res.attachment(fileKey);
    var fileStream = s3.getObject(options).createReadStream();
    fileStream.pipe(res);
});

var server = app.listen(3000, function () {
    var Host = server.address().address;
    var port = server.address().port;
    console.log('S3 Proxy app listening at http://%s:%s', Host, port);
});
40
Yash Dayal

このコードは、最新のライブラリで機能しました:

var s3 = new AWS.S3();
var s3Params = {
    Bucket: 'your bucket',
    Key: 'path/to/the/file.ext'
};
s3.getObject(s3Params, function(err, res) {
    if (err === null) {
       res.attachment('file.ext'); // or whatever your logic needs
       res.send(data.Body);
    } else {
       res.status(500).send(err);
    }
});
12
SebastianView

問題を解決するために最も重要なことはすでにわかっています。S3からのファイルストリームを、書き込み可能なストリームにパイプすることができます。

s3.GetObject(options, { stream : true }, function(err, data) {
    res.attachment('test.pdf');
    data.Stream.pipe(res);
});

res.attachment を使用すると、正しいヘッダーが設定されることに注意してください。また、ストリームとS3について この回答 も確認できます。

6
Paul Mougel