我的情景:
我有一个使用MEEN堆栈编写的应用程序(MySQL,ExpressJS,EmberJS,NodeJS)。在页面中,我有一个表单输入。我应该获取输入数据,将其发送到服务器,生成PDF并在EmberJS中显示。服务器在带有ExpressJS的NodeJS中,生成的文件在发送到前端之前写入磁盘。
我的问题:
我无法在EmberJS中显示PDF文件。或者说,没有显示任何内容。在NodeJS和ExpressJS的后端,我将PDF文件的文件流发送回EmberJS。在Chrome中使用像Postman扩展名这样的REST客户端,会调用该对话框,我可以保存该文件。但是,在EmberJS中,没有出现对话框,但我可以在Chrome开发工具中使用console.log
查看文件流的内容。
为什么会这样?
以下是我使用ExpressJS在NodeJS中发送文件的代码。
generatePDF: function(req, res){
var details = req.body;
// @param details
// @return relative path to the file
inventoryController.generatePDF(details, function(relPath){
var filePath = path.resolve(relPath);
// This is the first method
// I explicitly specify the header for the Response Object
// and pipe the ReadableStream to the Response Object
// var name = path.basename(filePath);
// var mimeType = mime.lookup(filePath);
// res.setHeader('Content-disposition', 'attachment; filename=' + name);
// res.setHeader('Content-type', mimeType);
// var fileStream = fs.createReadStream(filePath);
// fileStream.pipe(res);
// This is the second method (currently being used)
// using sendfile() of ExpressJS, the header is automatically set
res.sendfile(filePath);
});
},
Ember.js中的代码,用于向服务器发送详细信息并获取数据。
var doc = {
// some attributes inside here
};
var url='/pdf';
var request = Ember.$.post(url, doc);
request.then(function(data){
if(data.status === 'ERR'){
// handling error
} else {
console.log('Successfully generated PDF.');
console.log(data); // I can see the filestream here
}
});
答案 0 :(得分:1)
我认为问题在于这不是Ember.js问题,而是服务器问题,以及它是如何处理的。 jQuery无法将文件保存到磁盘,因为它存在安全风险。虽然扩展可以覆盖各种安全限制,但在Ember或任何其他JavaScript框架(使用jQuery)中,您不能强制将另存为对话框,因为这是由安全性强制执行的。 JavaScript无法写入您的本地文件格式(除了html 5本地存储,它在很多方面与cookie类似)。
因此,您无法以PDF格式保存。可能让它工作的唯一方法是允许浏览器本身捕获流并处理它:
你可以尝试这个plugin,但我不确定它是否有效,而且根本不推荐。
我建议你只使用浏览器中的纯链接,让服务器以适当的方式发回文件,而不是ajax调用。您可以使用表单提交它,也可以使用带有查询字符串参数的纯链接。
客户端:
<a href="/server/getFile?{"contentID"="123", "user" = "test@me"}>Get File</a>
或
<form action="/getFile" method="POST">
<input type="hidden" id="user" name="user" value="test@me" />
<input type="hidden" id="contentID" name="contentID" value="123" />
<input type="submit" value="Get File />
</form>
服务器端:
在服务器中添加以下标题:
res.setHeader('Content-disposition', 'attachment; filename=<file name.ext>');
添加mime-type可能是个明智的想法:
res.setHeader('Content-type', '<type>/<subtype>');
完整代码:
var filename = path.basename(filePath);
res.setHeader('Content-disposition', 'attachment; filename='+ filename);
res.setHeader('Content-type', 'application/pdf');
// it's better to use a stream than read all the file into memory.
var filestream = fs.createReadStream(filePath);
filestream.pipe(res);
或者,如果您使用快递,则可以使用此helper
res.download(filePath)