web-dev-qa-db-ja.com

Pdf.jsおよびviewer.js。ストリームまたはblobをビューアに渡す

この解決策を見つけるのに問題があります:この方法でJavascriptを使用してSQLファイルストリームフィールドからPDF blobを取得します(これはlightswitchプロジェクトです)

var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });

BLOBがあり、ファイルストリームまたはbase64( "JVBERi0 ....."または "%PDF 1.6 ......"など)に変換することもできます。

今のところ問題ありません。

次に、ビューアーで表示する必要があります。ビューアーを新しいウィンドウで開くことを好みますが、どうにかしてページに埋め込むために開いています。

ブロブまたはストリームをビューアーに直接渡し、ドキュメントを表示できるかどうか疑問に思っています。私は次のようなものを試しました

PDFView.open(pdfAsArray, 0)

この場合、埋め込みビューアでは何も起こりません。

pdfAsArrayは、同じページ内のキャンバスにストリームを追加して表示できるため、優れています。 PDFをキャンバス、おそらく新しいウィンドウに埋め込むのではなく、ビューアを表示したいだけです。

Javascriptでそれを実現する方法について、誰でも数行のコードを提供できますか?

22
Efrael

私はついにPDFView.openメソッドを機能させました。ここで、ビューアーをページに埋め込み、Robが最初の2つの例で提案したようにopen関数を呼び出した場合、機能します。

この種のソリューションを探している人のために、ここでいくつかのコード行を提供します。

これは、Lightswitch mainPage.lsml.jsのコードです。jsスクリプト(pdf.js、ビューアー、その他)は、Lightswitchプロジェクトのメインhtmlページ(Default.html)で参照されます。 Lightswitchベースではない他のHTMLページでも動作するはずです。

myapp.MainPage.ShowPdf_execute = function (screen) {
// Write code here.
// Getting the stream from sql
var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });
// Pass the stream to an aspx page that makes some manipulations and returns a response
var formData = new FormData();
formData.tagName = pdfName;
formData.append(pdfName, blob);
var xhr = new XMLHttpRequest();
var url = "../OpenPdf.aspx";
xhr.open('POST', url, false);
xhr.onload = function (e) {
    var response = e.target.response;
        var pdfAsArray = convertDataURIToBinary("data:application/pdf;base64, " + response);
        var pdfDocument;
// Use PDFJS to render a pdfDocument from pdf array
    PDFJS.getDocument(pdfAsArray).then(function (pdf) {
        pdfDocument = pdf;
        var url = URL.createObjectURL(blob);
        PDFView.load(pdfDocument, 1.5)
    })
};
xhr.send(formData);  // multipart/form-data 
};

これはconvertDataURIToBinary関数です

function convertDataURIToBinary(dataURI) {
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));

for (i = 0; i < rawLength; i++) {
    array[i] = raw.charCodeAt(i);
}
return array;
}

まだ見逃しているのは、新しいウィンドウでストリームを開き、レンダリングを行う別のUIを持つために、viewer.htmlページにストリームを直接渡す可能性です。

内部にドキュメントのない空のビューアを取得したため、このコードはまだ機能していません

var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });
var url = URL.createObjectURL(blob);
var viewerUrl = 'Scripts/pdfViewer/web/viewer.html?file=' + encodeURIComponent(url);
window.open(viewerUrl);

EncodeURIComponent(url)は、ビューアーにロードする適切なオブジェクトをビューアーに渡していないようです。アイデアや提案はありますか?

9
Efrael

PDFJS.version = '1.0.1040'; PDFJS.build = '997096f';を使用しています

Base64 pdfデータをロードするために私のために働いたコードはこれでした:

function (base64Data) {
  var pdfData = base64ToUint8Array(base64Data);
  PDFJS.getDocument(pdfData).then(function (pdf) {
    pdf.getPage(1).then(function (page) {
      var scale = 1;
      var viewport = page.getViewport(scale);
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      canvas.height = viewport.height;
      canvas.width = viewport.width;
      page.render({ canvasContext: context, viewport: viewport });
    });
  });

  function base64ToUint8Array(base64) {
    var raw = atob(base64);
    var uint8Array = new Uint8Array(raw.length);
    for (var i = 0; i < raw.length; i++) {
      uint8Array[i] = raw.charCodeAt(i);
    }
    return uint8Array;
  }
}

この関数は、API呼び出しプロミスの成功関数です。ここで行っているのは、pdfをcanvas要素myCanvasにレンダリングすることです。

<canvas id="myCanvas"></canvas>

これは、pdfの最初のページを示していますが、機能はありません。視聴者が望ましい理由を見ることができます。これをビューア(viewer.html/viewer.js)に接続したら、答えを編集します。

編集:ビューアの接続方法

1bower.jsonに、"pdfjs-viewer": "1.0.1040"を追加します

2 HTML:

<iframe id="pdfViewer" src="lib/pdfjs-viewer/web/viewer.html" style="width: 100%; height: 700px;" allowfullscreen="" webkitallowfullscreen=""></iframe>

viewer.jsファイルの愚かなデフォルトドキュメントを変更します。

var DEFAULT_URL = '';

4コントローラー:

var pdfjsframe = document.getElementById('pdfViewer');
pdfjsframe.onload = function() {
  LoadPdfDocument();
};

$scope.myApiCallThatReturnsBase64PdfData.then(
  function(base64Data) {
    $scope.base64Data = base64Data;
    LoadPdfDocument();
  },
  function(failure) {

    //NotificationService.error(failure.Message);

  });

function LoadPdfDocument() {
  if ($scope.PdfDocumentLoaded)
    return;
  if (!$scope.base64Data)
    return;

  var pdfData = base64ToUint8Array($scope.base64Data);
  pdfjsframe.contentWindow.PDFViewerApplication.open(pdfData);

  $scope.PdfDocumentLoaded = true;
}

function base64ToUint8Array(base64) {
  var raw = atob(base64);
  var uint8Array = new Uint8Array(raw.length);
  for (var i = 0; i < raw.length; i++) {
    uint8Array[i] = raw.charCodeAt(i);
  }
  return uint8Array;
}
20
toddmo

型付き配列(_Uint8Array_など)がある場合は、PDFView.open(typedarray, 0);を使用してファイルを開くことができます。

BlobまたはFileオブジェクトがある場合は、データを表示する前に型付き配列に変換する必要があります。

_var fr = new FileReader();
fr.onload = function() {
    var arraybuffer = this.result;
    var uint8array = new Uint8Array(arraybuffer);
    PDFView.open(uint8array, 0);
};   
fr.readAsArrayBuffer(blob);
_

別の方法は、Blob/FileオブジェクトのURLを作成することです。

_var url = URL.createObjectURL(blob);
PDFView.open(url, 0);
_

PDF Viewerが 同じOrigin で、フレームを埋め込むWebサイトとしてホストされている場合、PDF blob URLをビューアに渡すことにより:

_var url = URL.createObjectURL(blob);
var viewerUrl = 'web/viewer.html?file=' + encodeURIComponent(url);
// TODO: Load the PDF.js viewer in a frame or new tab/window.
_
8
Rob W
var url = URL.createObjectURL(blob);

var viewerUrl = 'web/viewer.html?file=' + encodeURIComponent(url);

// TODO: Load the PDF.js viewer in a frame or new tab/window.

//-- Abobe code opens a new window but with errors : 'Missing PDF 
// blob://http://server-addr:port/converted-blob' 
3