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

时间:2015-04-10 13:39:11

标签: angularjs node.js express mean-stack

我正在处理使用https://github.com/DaftMonk/generator-angular-fullstack生成的meanjs应用程序。我正在尝试使用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位计算机上运行它

4 个答案:

答案 0 :(得分:4)

这是一种从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);
});

答案 1 :(得分:3)

通常如果您使用幻像生成pdf,那么该文件将被写入光盘,您必须提供路径和回放到渲染功能。

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

答案 2 :(得分:3)

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

  1. 如果文件是静态文件,如宣传册,自述文件等,那么你可以告诉快递我的文件夹有静态文件(并且应该可以直接使用)并保存文件。这是使用静态中间件完成的: app.use(express.static(pathtofile)); 这是链接:http://expressjs.com/starter/static-files.html
  2. 现在您可以使用浏览器中的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');

    2. 然后设置内容类型:

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

      并将数据作为响应发送。 我将尝试举例说明这一点。

      编辑:你甚至不需要编码。你可以尝试一下。但是我甚至没有编码就能使它工作。

      另外,您也不需要设置标题。 Express为您服务。以下是为获取pdf而编写的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。否则它将保存文件而不进行任何扩展。

答案 3 :(得分:0)

我没有您所提到的框架的经验,但我建议使用像Fiddler这样的工具来查看正在发生的事情。例如,您可能不需要添加内容长度标头,因为您正在流式传输,并且您的框架会进行分块传输编码等。