web-dev-qa-db-ja.com

PDF.JS:URLの代わりにArrayBufferまたはBlobを使用してPDF

私はこれに似た質問を知っています: Pdf.js:urlの代わりにbase64ファイルソースを使用してpdfファイルをレンダリングする 。その質問は Codetoffel によって素晴らしく答えられましたが、私の質問は、私のPDFが私のWebAPI実装へのRESTful呼び出しを介して取得されるという点で異なります。説明させてください...

まず、PDF.JSを使用してURL経由でPDFを開く基本的な方法は次のとおりです。

PDFJS.getDocument("/api/path/to/my.pdf").then(function (pdf) {
  pdf.getPage(1).then(function (page) {
    var scale = 1;
    var viewport = page.getViewport(scale);
    var canvas = document.getElementById('the-canvas');
    var context = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    page.render({canvasContext: context, viewport: viewport});
  });
});

これはうまく機能しますが、私はAngularとその$resourceサービスを使用して、RESTful WebAPIを介してPDFをリクエストします。 PDF.JSを使用すると、PDFJS.getDocumentメソッド(上記)で文字列としてURLを渡すことを、定義されているDocumentInitParamsオブジェクトに置き換えることができます ここ 。DocumentInitParamsオブジェクトを使用する次のように機能します。

var docInitParams = {
    url: "/api/path/to/my.pdf",
    httpHeaders: getSecurityHeaders(), //as needed
    withCredentials: true
};
PDFJS.getDocument(docInitParams).then(function (pdf) {
    ...
});

これも機能しますが、API URLを作成するように要求することで、私のAngular $resourceを回避します。ただし、PDFJSではPDFします。

var myPdf = myService.$getPdf({ Id: 123 });

//It's an Angular $resource, so there is a promise to be fulfilled...
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf
    };
    PDFJS.getDocument(docInitParams).then(function (pdf) {
        ...
    });
});

これは私が仕事に就けないように見えるものです。 myService.$gtPdfメソッドにデータをblobまたはarraybufferとして返すように指示できますが、どちらも機能しません。配列バッファから返されたデータもUint8Arrayに変換しようとしましたが、役に立ちませんでした。

他に何を試すべきかわからないので、実際にチップを使うことができます。

サービスから返されたデータをPDFJSで機能させるにはどうすればよいですか?

前もって感謝します。

10
witttness

応答データをPDF.jsに渡すのではなく、リソースのインスタンスを渡します。

var myPdf = myService.$getPdf({ Id: 123 });
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf

$getPdfのコードは表示されていませんが、これは同等のものだと思います

var myService = $resource('/foo', {}, {$getPdf:{responseType: 'arraybuffer'}});
var myPdf = myService.$getPdf();

デフォルトでは、AngularJS $resourceは応答をオブジェクト(JSONから逆シリアル化)として扱い、すべてのプロパティをオブジェクトからリソースインスタンス(前のスニペットのmyPdf)にコピーします。

明らかに、応答は配列バッファー(または、Blob、型付き配列など)であるため、これは機能しません。目的の応答を取得する方法の1つは、transformResponseを使用して応答オブジェクトをオブジェクトにラップすることです。

var myService = $resource('/foo', {}, {
    $getPdf: {
        responseType: 'arraybuffer',
        transformResponse: function(data, headersGetter) {
            // Stores the ArrayBuffer object in a property called "data"
            return { data : data };
        }
    }
});
var myPdf = myService.$getPdf();
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf.data
    };

    PDFJS.getDocument(docInitParams).then(function (pdf) {
        // ...
    });
});

または、単に次のようにします(不要なローカル変数を回避します)。

myService.$getPdf().$promise.then(function(myPdf) {
    PDFJS.getDocument({
        data: myPdf.data
    }).then(function (pdf) {
        // ...
    });
});
19
Rob W