javascript 使用express js在浏览器中显示PDF

8e2ybdfx  于 2023-02-11  发布在  Java
关注(0)|答案(7)|浏览(178)

我试图通过Express以浏览器中显示的方式提供PDF:

app.post('/asset', function(request, response){
  var tempFile="/home/applmgr/Desktop/123456.pdf";
  fs.readFile(tempFile, function (err,data){
     response.contentType("application/pdf");
     response.send(data);
  });
});

但是,浏览器显示二进制内容,如何正确处理?

dgjrabp2

dgjrabp21#

指定如何处理文件下载都归结为Content-disposition头文件。您也可以在这里指定文件名。我们还设置了Content-type以确保浏览器知道如何处理给定的文件。

Express.js示例:

app.post('/url/to/hit', function(req, res, next) {
  var stream = fs.crateReadStream('/location/of/pdf');
  var filename = "WhateverFilenameYouWant.pdf"; 
  // Be careful of special characters

  filename = encodeURIComponent(filename);
  // Ideally this should strip them

  res.setHeader('Content-disposition', 'inline; filename="' + filename + '"');
  res.setHeader('Content-type', 'application/pdf');

  stream.pipe(res);
});

现在,如果您更仔细地观察Content-disposition,您会注意到inline;字段用于设置浏览器对文件的React。
我也发现(被刻录了几次),如果你在文件名中设置特殊字符,它可能会崩溃,所以我encodeURIComponent()文件名,以确保不会发生这种情况。
希望这对其他想要弄清楚同样问题的人有帮助!

编辑

从我最初发布这篇文章到现在,我已经找到了如何正确编码content-disposition的filename参数。根据规范,文件名应该是RFC5987编码的。我最终从MDN找到了一个示例代码片段,正确处理了这里的编码(encodeURIComponent()不是这个字段的完全正确的格式)。

MDN代码段

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" 
             + encodeRFC5987ValueChars(fileName);

console.log(header); 
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"

function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            // so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

在此之上的另一个注意事项是,浏览器也不完全符合规范。一些字符仍然会从下载中错误地返回(至少在我测试它的时候)。
你可以通过更新下载的工作方式来解决这个问题。如果你的下载URL以文件名结尾(并且你没有在头中提供filename属性),它将正确地从URL编码值中获取文件名。IE 'http://subdomain.domain-url.com/some/path/to/downloads/' + encodeURIComponent("You're there, download this!.pdf")
jeeze,和所有提供一个文件名到您的下载!

o0lyfsai

o0lyfsai2#

我测试了你的代码,它为我在chrome的一个变化:将app.post更改为app.get
编辑:既然你认为只支持POST的服务器是个好主意,请阅读以下内容:http://net.tutsplus.com/tutorials/other/a-beginners-introduction-to-http-and-rest/向下滚动到HTTP predicate ,并查看GET和POST之间的区别。:)
一些快速的研究表明,其他浏览器可能有其他问题,例如IE可能会期望URL以.pdf结尾,因为我在Mac上,我不能为你测试;)

z9smfwbn

z9smfwbn3#

我的直接发送PDF到浏览器的解决方案:

app.get('/my/pdf', function (req, res) {
    var doc = new Pdf();
    doc.text("Hello World", 50, 50);

    doc.output( function(pdf) {
        res.type('application/pdf');
        res.end(pdf, 'binary');
    });
});

在我的例子中,第二个参数为'binary'的res.end()就起到了作用,否则express会将其解释为字符串

7eumitmz

7eumitmz4#

其实快递已经有这个功能发送文件,你所需要的是:

app.get('/sendMePDF', function(req, res) {
  res.sendFile(__dirname + "/static/pdf/Rabbi.pdf");
})

这里服务器将发送文件“Rabbi.pdf”,它将在浏览器中打开,就像您在浏览器中打开PDF一样。我将文件放在“static”文件夹中,但您可以将其放在任何位置,因为sendFile()将绝对路径(而不是相对路径)作为参数。

blmhpbnm

blmhpbnm5#

它就像下面的代码一样简单:

var express = require('express'),
    fs = require('fs'),
    app = express();

app.get('/', function (req, res) {
    var filePath = "/files/my_pdf_file.pdf";

    fs.readFile(__dirname + filePath , function (err,data){
        res.contentType("application/pdf");
        res.send(data);
    });
});

app.listen(3000, function(){
    console.log('Listening on 3000');
});
  • 完整回购 *:

克隆节点欺骗pdf_browser,运行node app,然后运行npm install express
乐于助人!

dced5bon

dced5bon6#

根据Express js文档,您可以在一个函数中设置内容类型和内容处置,如下所示

fs.readFile(filePath, (err, data) => {
res.set({
  "Content-Type": "application/pdf", //here you set the content type to pdf
  "Content-Disposition": "inline; filename=" + fileName, //if you change from inline to attachment if forces the file to download but inline displays the file on the browser
});
res.send(data); // here we send the pdf file to the browser
});
hsvhsicv

hsvhsicv7#

post('/fileToSend/', async (req, res) => {

  const documentPath = path.join(
    __dirname,
    '../assets/documents/document.pdf'
  );
    
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', 'attachment; filename=document.pdf');

  return res.download(documentPath);
});

相关问题