36

ブラウザーに表示される方法で 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);
  });
});

ただし、ブラウザにはバイナリ コンテンツが表示されます。これを正しく処理するには?

4

7 に答える 7

37

ファイルのダウンロードがどのように処理されるかを指定することは、すべて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);
}

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

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

ダウンロードにファイル名を指定するためです。

于 2014-02-14T19:58:39.410 に答える
13

私はあなたのコードをテストしました、そしてそれは1つの変更でクロームで私のために働きますapp.postapp.get

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

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

于 2012-07-22T18:23:07.243 に答える
11

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() がうまくいきました。それ以外の場合は、明示的に文字列として解釈します

于 2012-11-23T17:03:12.130 に答える
6

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

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.

ハッピーヘルプ!

于 2016-03-19T08:12:05.860 に答える