2014-03-03 192 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)和[there](http://stackoverflow.com/a/14683228/2137601)) )。你可以做的是让用户用'dlKey'数据发送POST FORM。 –

回答

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,将设置正确的头。您还可以查看有关流和S3的this answer

+0

感谢您的快速发布! 您建议的代码编译文件,看起来像 - 如果它应该工作,但它仍然不会提示我在safari或chrome上有下载对话框!我找不到为什么,因为它现在应该有一个附件头 – 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返回的对象没有2015年示例中所示的.createReadStream()方法。回调中的数据对象没有数据。在2014年的示例中显示的流属性。 – antonycc

相关问题