web-dev-qa-db-ja.com

Express jsを使用してブラウザーで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);
  });
});

私はexpressjsの初心者であり、データオブジェクトと共に応答を送信できません。バイナリコンテンツはブラウザに表示されます。これを処理する方法を教えてください?

26
Dexter

コードをテストしましたが、chromeで1つの変更を加えて動作します:Change app.postからapp.get

編集:POST専用サーバーは良い考えだと思われるので、これを読んでください: http://net.tutsplus.com/tutorials/other/a-beginners-introduction-to-http-and- rest / HTTP動詞までスクロールダウンし、GETとPOSTの違いを確認します。 :)

いくつかの簡単な調査では、他のブラウザには他の問題がある可能性があることが示唆されています。IEたとえば、URLが.pdf。私は私のMacにいるので、あなたのためにそれをテストすることはできません;)

8
rdrey

ファイルのダウンロードの処理方法の指定はすべて、_Content-disposition_ヘッダーに委ねられます。ここでもファイルの名前を指定できます。また、_Content-type_を設定して、与えられたファイルをブラウザがどうするかをブラウザが認識できるようにします。

Express.jsの例:

_app.post('/url/to/hit', function(req, res, next) {
  var stream = fs.readStream('/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;_フィールドが、ブラウザーがファイルにどのように反応するかを設定していることがわかります。ダウンロードを強制する場合は、_inline;_を_attachment;_に設定することでダウンロードできます。

また、ファイル名に特殊文字を設定すると、壊れる可能性があることも(何度か焼かれて)わかっています。そのため、ファイル名をencodeURIComponent()し、それが起こらないようにします。

他の人が同じことを理解しようとしていることを願っています!

編集

最初にこれを投稿してから現在までに、_content-disposition_のファイル名パラメーターを正しくエンコードする方法を見つけました。 仕様によると、ファイル名は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);
}
_

これに加えて、ブラウザーも仕様に完全には準拠していません。いくつかのキャラクターは、ダウンロードから間違って戻ってきます(少なくとも私がテストしたとき)。

ダウンロードの動作を更新することで、thisの問題を回避できます。ダウンロードURLがファイル名で終わる場合(およびヘッダーにfilename属性を指定しない場合)、URLエンコードされた値からファイル名を正しく取得します。 IE 'http://subdomain.domain-url.com/some/path/to/downloads/' + encodeURIComponent("You're there, download this!.pdf")

Jeeze、およびすべてがダウンロードにファイル名を提供します!

27
AlbertEngelB

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

私の場合、2番目のパラメーター 'binary'を指定したres.end()がうまくいきました。それ以外の場合は、文字列として解釈します

10
sja

次のコードと同じくらい簡単です。

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

完全なレポの場合

Node-cheatの複製 pdf_browser 、実行node app に続く npm install express

ハッピーヘルプ!

実際には、エクスプレスにはファイルをリモートに送信する機能があります。あなたに必要なのは :

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

ここで、サーバーはファイル「Rabbi.pdf」を送信し、ブラウザーでpdfを開くようにブラウザーで開きます。ファイルを「静的」フォルダーに配置しましたが、sendFile()が絶対パス(相対パスではなく)を引数として取ることがわかっているため、どこにでも配置できます。

0
Peco