繁体   English   中英

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

[英]NodeJS not trigger save file dialog in browser / EmberJS not receive file sent from server

我的情况
我有一个使用MEEN堆栈(MySQL,ExpressJS,EmberJS,NodeJS)编写的应用程序。 在页面中,我有一个表单输入。 我应该获取输入数据,将其发送到服务器,生成PDF并在EmberJS中显示。 服务器位于带有ExpressJS的NodeJS中,并且在将生成的文件发送到前端之前将其写入磁盘。

我的问题

我无法在EmberJS中显示PDF文件。 或更确切地说,什么也不显示。 在使用NodeJS和ExpressJS的后端中,我将PDF文件的文件流发送回EmberJS。 使用REST客户端(如Chrome中的Postman扩展名),将调用对话框,我可以保存文件。 但是,在EmberJS中,没有对话框出现,但是我可以使用Chrome Dev Tools中的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
    }
});

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

因此,您不能另存为PDF。 可能使它起作用的唯一方法是允许浏览器本身捕获流并对其进行处理:

您可以尝试使用此插件 ,但是我不确定它是否有效,并且完全不建议使用。

我建议您只使用浏览器中的纯链接,然后让服务器以正确的方式发送文件,而不是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类型可能是一个明智的想法:

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM