使用expressjs时,下载的.pdf文件已损坏

我正在使用https://github.com/DaftMonk/generator-angular-fullstack生成的meanjs应用程序。 我正在尝试使用phantomjs生成.pdf文件并将其下载到浏览器。

问题是,无论页面数量多less,下载的.pdf文件总是显示空白页面。 服务器上的原始文件没有损坏。 当我进一步调查时,发现下载的文件总是比磁盘上的原始文件大得多。 此外,这个问题只发生在.pdf文件中。 其他文件types工作正常。

我已经尝试了几种方法,如res.redirect('http://localhost:9000/assets/exports/receipt.pdf');res.download('client\\assets\\exports\\receipt.pdf')

 var fileSystem = require('fs'); var stat = fileSystem.statSync('client\\assets\\exports\\receipt.pdf'); res.writeHead(200, { 'Content-Type': 'application/pdf', 'Content-Length': stat.size }); var readStream = fileSystem.createReadStream('client\\assets\\exports\\receipt.pdf'); return readStream.pipe(res); 

甚至我已经尝试了https://github.com/expressjs/serve-static没有改变的结果。

我是nodejs 。 将.pdf文件下载到浏览器的最佳方法是什么?

更新:我在Windows 8.1 64位计算机上运行此

下面是一个干净的方式来expression一个文件,并使用一个attachment头来确保文件被下载:

 var path = require('path'); var mime = require('mime'); app.get('/download', function(req, res){ //Here do whatever you need to get your file var filename = path.basename(file); var mimetype = mime.lookup(file); res.setHeader('Content-disposition', 'attachment; filename=' + filename); res.setHeader('Content-type', mimetype); var filestream = fs.createReadStream(file); filestream.pipe(res); }); 

我在静态的pdf文件上也有腐败现象。 我尝试了上面提到的一切。 然后我发现这个: https : //github.com/intesso/connect-livereload/issues/39从本质上来说,通常优秀的connect-livereload(package〜0.4.0)正在破坏pdf。 所以只是让它忽略pdfs通过:

 app.use(require('connect-livereload')({ignore: ['.pdf']})); 

现在这个作品:

 app.use('/pdf', express.static(path.join(config.root, 'content/files'))); 

…很好的解脱

通常,如果您正在使用phantom来生成pdf,那么文件将被写入光盘,您必须提供path和callback函数。

 router.get('/pdf', function(req, res){ // phantom initialization and generation logic // supposing you have the generation code above page.render(filePath, function (err) { var filename = 'myFile.pdf'; res.setHeader('Content-type', "application/pdf"); fs.readFile(filePath, function (err, data) { // if the file was readed to buffer without errors you can delete it to save space if (err) throw err; fs.unlink(filePath); // send the file contents res.send(data); }); }); }); 

有几种方法可以做到这一点:

  1. 如果文件是一个像小册子,自述等静态文件,那么你可以告诉表明,我的文件夹有静态文件(应该可以直接使用),并保留在那里的文件。 这是使用静态中间件完成的:app.use(express.static(pathtofile)); 这里是链接: http : //expressjs.com/starter/static-files.html

现在你可以使用浏览器中的URL直接打开文件,如:

 window.open('http://localhost:9000/assets/exports/receipt.pdf'); 

要么

 res.redirect('http://localhost:9000/assets/exports/receipt.pdf'); 

应该工作。

  1. 第二种方法是读取文件,数据必须作为缓冲区来传递。 实际上,如果你直接发送它,应该被认可,但你可以尝试使用下面的代码将它转换成base64编码:

    var base64String = buf.toString('base64');

然后设置内容types:

 res.writeHead(200, { 'Content-Type': 'application/pdf', 'Content-Length': stat.size }); 

并作为回应发送数据。 我会试着举一个这样的例子。

编辑:你甚至不需要编码。 你可以试试。 但是我甚至可以在没有编码的情况下使其工作。

另外你也不需要设置标题。 快递为你做。 以下是编写的API代码片段,以防万一它不是公共/静态的。 您需要API来提供PDF:

 router.get('/viz.pdf', function(req, res){ require('fs').readFile('viz.pdf', function(err, data){ res.send(data); }) }); 

最后,请注意,获取PDF的url有PDF扩展名,这是浏览器识别传入文件是pdf。 否则,它将保存文件没有任何扩展名。

我没有你提到的框架的经验,但我会build议使用像Fiddler这样的工具来看看发生了什么。 例如,你可能不需要添加一个内容长度的头,因为你是stream媒体,你的框架没有分块传输编码等