2014-03-03 5 views
17

Моя цель:NodeJS Как загрузить файл на диск из ведра aws s3?

Показать диалоговое окно, предлагающее пользователю сохранить файл, загружаемый с aws.

Моя проблема:

настоящее время я использую awssum-амазонка-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!'); 
     }); 
    }; 

Цель этого кода, чтобы позволить пользователям использовать сгенерированный ключ для загрузки файла один раз.

+0

К сожалению, вы не можете скачать файл на диск пользователя через запросы AJAX (см. [здесь] (http://stackoverflow.com/a/9970672/2137601) и [там] (http://stackoverflow.com/a/14683228/2137601), например). Вместо этого вы можете сделать команду POST FORM с данными 'dlKey'. –

ответ

23

Это весь код, с помощью потоковой передачи на последней версии 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); 
}); 
+1

Я понятия не имел. '.createReadStream()' это вещь. Спасибо за этот пример! – btleffler

5

Вы уже определились с тем, что наиболее важно для решения вашей проблемы: вы можете передать поток файлов, поступающий из S3, в любой записываемый поток, будь то файл-поток ... или поток ответов, который будет отправлен клиенту!

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

Обратите внимание на использование res.attachment, который установит правильные заголовки. Вы также можете посмотреть this answer относительно потоков и S3.

+0

Спасибо за быстрый пост! Код, который вы предложили, компилирует файл и выглядит так: если он должен работать, он все равно не подсказывает мне диалог загрузки на сафари или хром! Я не могу понять, почему, так как теперь он должен иметь заголовок вложения. – gbachik

+0

Не соответствует ли это поведение (запрос пользователя для места загрузки), связанное с конфигурацией браузера? –

+0

Да, но даже с правильной конфигурацией я не получаю подсказки. Это даже не загрузка (сервер или локальный). Я также обновляю свой вопрос с помощью своего углового кода, потому что, возможно, это проблема. – gbachik

5

Этот код работает для меня с последней библиотекой:

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); 
    } 
}); 
+0

'' aws-sdk ":"^2.7.20 ",' – antonycc

+0

data.Body - это буфер, который поддерживает toString(). Объект, возвращаемый getObject, не имел метода .createReadStream(), показанного в примере с 2015 года. Там, где объект данных в обратном вызове не имел данных.Поток, показанный в примере с 2014 года. – antonycc

Смежные вопросы