NodeJS在浏览器中不触发保存文件对话框/ EmberJS不接收从服务器发送的文件

我的场景
我有一个使用MEEN堆栈(MySQL,ExpressJS,EmberJS,NodeJS)编写的应用程序。 在一个页面中,我有一个表单input。 我应该得到input的数据,发送到服务器,生成一个PDF,并显示在EmberJS。 服务器使用ExpressJS在NodeJS中,生成的文件在发送到前端之前写入磁盘。

我的问题

我无法在EmberJS中显示PDF文件。 或者说,什么都不显示。 在我用NodeJS和ExpressJS的后端,我发送PDF文件的文件stream回到EmberJS。 在Chrome中使用邮递员扩展等REST客户端,对话框被调用,我可以保存文件。 但是,在EmberJS中,没有出现对话框,但是我可以在Chrome开发工具中使用console.log来查看文件stream的内容。
为什么这样?

下面是我用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 } }); 

我认为问题在于,这不是Ember.js问题,而是服务器问题,以及如何处理。 jQuery无法将文件保存到磁盘,因为这是一个安全风险。 虽然扩展可以覆盖各种安全限制,但在Ember或任何其他JavaScript框架(使用jQuery)时,您不能强制另存为对话框,因为这是由安全性强制执行的。 JavaScript不能写入你的本地文件格式,(除了HTML 5的本地存储,在许多方面类似于cookie)。

因此,您不能保存为PDF。 让这个工作的唯一方法是允许浏览器自己捕获stream并处理它:

你可以尝试这个插件 ,但我不知道它的工作原理,而且根本不推荐。

我build议你只使用来自浏览器的纯链接,让服务器以正确的方式发回文件,而不是使用ajax调用。 你可以有一个表单提交它或纯粹的链接查询string参数。

客户端:

 <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>'); 

也可以添加一个MIMEtypes:

 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); 

或者如果你使用快递,你可以使用这个帮手

 res.download(filePath)