How do I serve a file from S3 through Meteor Iron Router

孤街浪徒 提交于 2019-12-07 12:10:25

问题


My question is very similar to this one which describes how to serve a local file using Iron Router. I need to do the same, but instead of reading the file synchronously from disk, I need to get the file from S3 which is an asynchronous call.

The problem appears to be the fact that the action method has returned before the asynchronous s3.getObject completes giving me the following error.

Error: Can't render headers after they are sent to the client.

I'm assuming that Iron Router is generating the response for me when it realizes that I haven't handled the response in my action method, but I'm stumped about how to tell it to wait for my asynchronous call to finish.

Here is my code.

Router.map(function () {
    this.route('resumeDownload', {
        where: 'server',
        path: '/resume/:_id',
        action: function () {
            var response = this.response;

            var candidate = Candidates.findOne(this.params._id);
            if (!candidate || !candidate.resumeS3Key) {
                // this works fine because the method hasn't returned yet.
                response.writeHead(404);
                return response.end();
            }

            var s3 = new AWS.S3();
            s3.getObject({Bucket: 'myBucket', Key: candidate.resumeS3Key}, function (err, data) {
                if (err) {
                    // this will cause the error to be displayed
                    response.writeHead(500);
                    return response.end();
                }
                // this will also cause the error to be displayed
                response.writeHead(200, {'Content-Type': data.ContentType});
                response.end(data.Body);
            });
        }
    });
});

回答1:


I was able to solve this one myself. I needed to use a future in my action method.

Here is the working code.

Router.map(function () {
    this.route('resumeDownload', {
        where: 'server',
        path: '/resume/:_id',
        action: function () {
            var response = this.response,
                candidate = Candidates.findOne(this.params._id);

            if (!candidate || !candidate.resumeS3Key) {
                response.writeHead(404);
                return response.end();
            }

            var Future = Npm.require('fibers/future'),
                s3 = new AWS.S3(),
                futureGetObject = Future.wrap(s3.getObject.bind(s3)),
                data = futureGetObject({Bucket: 'myBucket', Key: candidate.resumeS3Key}).wait();

            response.writeHead(200, {'Content-Type': data.ContentType});
            response.end(data.Body);
        }
    });
});


来源:https://stackoverflow.com/questions/22515740/how-do-i-serve-a-file-from-s3-through-meteor-iron-router

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!