我的问题与this one非常相似,它描述了如何使用Iron Router提供本地文件。我需要做同样的事情,但我不是从磁盘同步读取文件,而是需要从S3获取文件,这是一个异步调用。
问题似乎是action
方法在异步s3.getObject
完成之前返回的事实给出了以下错误。
Error: Can't render headers after they are sent to the client.
我假设Iron Router在我意识到我没有处理action
方法中的响应时为我生成响应,但是我很难过如何告诉它等待我异步调用完成。
这是我的代码。
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);
});
}
});
});
答案 0 :(得分:4)
我能够自己解决这个问题。我需要在future
方法中使用action
。
这是工作代码。
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);
}
});
});