我正在使用生成的meanjs
应用程序https://github.com/DaftMonk/generator-angular-fullstack.我正在尝试使用phantomjs
生成一个.pdf文件并将其下载到浏览器。
问题是,无论页数多少,下载的.pdf文件总是显示空白页面。服务器上的原始文件未损坏。当我进一步调查时,发现下载的文件总是比磁盘上的原始文件大得多。同样,这个问题只发生在.pdf文件中。其他文件类型运行良好。
我尝试了几种方法,如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位计算机上运行此程序
我在提供静态pdf时也发生了损坏。我尝试了上面建议的一切。然后我发现:https://github.com/intesso/connect-livereload/issues/39本质上,通常出色的连接livereload(包约0.4.0)正在破坏pdf。因此,只需通过忽略PDF即可
app.use(require('connect-livereload')({ignore: ['.pdf']}));
现在这个工作:
app.use('/pdf', express.static(path.join(config.root, 'content/files')));
如释重负。
这里有一种从express提供文件的干净方法,并使用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);
});
有几种方法可以做到这一点:
- 如果文件是静态文件,如宣传册、自述等,那么你可以告诉express我的文件夹有静态文件(应该可以直接使用),并将文件保存在那里。这是使用静态中间件完成的: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');
应该起作用。
第二种方法是读取文件,数据必须作为缓冲区。事实上,如果你直接发送它,它应该被识别,但你可以尝试使用将其转换为base64编码
var base64String=buf.toString('base64');
然后设置内容类型:
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Length': stat.size
});
并发送数据作为响应。我将尝试举一个这样的例子。
编辑:你甚至不需要编码。你可以继续尝试。但我甚至不用编码就能让它工作
另外,您也不需要设置标题。Express为您服务。以下是API代码段,用于获取pdf,以防它不是公共/静态的。您需要API来提供pdf:
router.get('/viz.pdf', function(req, res){
require('fs').readFile('viz.pdf', function(err, data){
res.send(data);
})
});
最后,请注意,获取pdf的url有扩展名pdf,这是为了让浏览器识别传入文件是pdf。否则,它将保存没有任何扩展名的文件。
通常,如果您使用phantom生成pdf,则文件将被写入光盘,并且您必须向render函数提供路径和回调。
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);
});
});
});
我对你提到的框架没有经验,但我建议使用Fiddler这样的工具来查看发生了什么。例如,你可能不需要添加内容长度标头,因为你正在流媒体传输,而你的框架进行分块传输编码等。