web-dev-qa-db-fra.com

NodeJS Comment télécharger un fichier sur le disque à partir d'un compartiment aws s3?

Mon but:

Affichez une boîte de dialogue invitant l'utilisateur à enregistrer un fichier en cours de téléchargement depuis aws.

Mon problème:

J'utilise actuellement awssum-Amazon-s3 pour créer un flux de téléchargement. Cependant, je n'ai réussi qu'à enregistrer le fichier sur mon serveur ou à le diffuser sur la ligne de commande ... Comme vous pouvez le voir dans mon code, ma dernière tentative a été d'essayer de définir manuellement les en-têtes de disposition de contenu qui ont échoué. Je ne peux pas utiliser res.download () car les en-têtes ont déjà été définis?

Comment puis-je atteindre mon objectif?

Mon code pour le nœud:

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!');
    });

Mon code pour angulaire:

$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!');
        });
    };

Le but de ce code est de permettre aux utilisateurs d'utiliser une clé générée pour télécharger un fichier une fois.

28
gbachik

Ceci est le code entier utilisant le streaming sur la dernière version de 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

Ce code a fonctionné pour moi avec la bibliothèque la plus récente:

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

Vous avez déjà compris ce qui est le plus important pour résoudre votre problème: vous pouvez diriger le flux de fichiers provenant de S3 vers n'importe quel flux inscriptible, que ce soit un flux de fichiers… ou le flux de réponses qui sera envoyé au client!

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

Notez l'utilisation de res.attachment qui définira les en-têtes corrects. Vous pouvez également consulter cette réponse concernant les flux et S3.

6
Paul Mougel