NodeJS如何从aws s3存储桶将文件下载到磁盘?

时间:2014-03-03 10:01:20

标签: node.js amazon-web-services amazon-s3 download disk

我的目标:

显示一个对话框,提示用户保存从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!');
        });
    };

此代码的目的是让用户使用生成的密钥下载文件一次。

4 个答案:

答案 0 :(得分:33)

这是在最新版本的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 :(得分:12)

此代码适用于最新的库:

package org.sampletest;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IWorkbench;
import org.junit.Test;

import com.example.myplugin.MyPlugin

public class MyPluginTest{

    @Test
    public void testMyPlugin() throws Exception{
         // assume an empty workspace - "Run as JUnit Plugin Test can be configured to clear the workspace before each run.
         String name = "myPluginTestProject";
         IProjectDescription = ResourcesPlugin.getWorkspace().newProjectDescription(name);
         IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
         project.create(desc, new NullProgressMonitor());
         project.open(new NullProgressMonitor());
         IFile file = project.getFile("myPluginTestFile");
         InputStream source = getClass().getClassLoader().getResourceAsStream("sampleFile");
         file.create(source, IFile.FORCE, null);

         // Assuming MyPlugin has some operation on an IStructuredSelection
         MyPlugin plugin = new MyPlugin();
         IStructuredSelection selection = new StructuredSelection(file);
         plugin.invoke(selection);

         // Make some assertions...
    }
}

答案 2 :(得分:8)

只需从S3和WriteStream创建一个ReadStream到您要下载的位置。查找下面的代码。对我来说很完美:

var AWS = require('aws-sdk');
var path = require('path');
var fs = require('fs');

AWS.config.loadFromPath(path.resolve(__dirname, 'config.json'));
AWS.config.update({
  accessKeyId: AWS.config.credentials.accessKeyId,
  secretAccessKey: AWS.config.credentials.secretAccessKey,
  region: AWS.config.region
});

var s3 = new AWS.S3();
var params = {
  Bucket: '<your-bucket>', 
  Key: '<path-to-your-file>'
};
let readStream = s3.getObject(params).createReadStream();
let writeStream = fs.createWriteStream(path.join(__dirname, 's3data.txt'));
readStream.pipe(writeStream);

答案 3 :(得分:6)

您已经确定了解决问题的最重要因素:您可以将来自S3的文件流传输到任何可写流,无论是文件流......还是将发送到客户端的响应流!

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

请注意使用res.attachment来设置正确的标头。您还可以查看有关流和S3的this answer