Подтвердить что ты не робот

Pdf.js и viewer.js. Передайте поток или blob зрителю

У меня возникают проблемы с поиском решения для этого: Я извлекаю PDF-блок из поля filestream SQL, используя Javascript таким образом (это проект lightwitch)

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

У меня есть blob, и я могу даже преобразовать его в filestream или base64 ( "JVBERi0....." или "% PDF 1.6......" и т.д.)

Пока нет проблем.

Теперь мне нужно отобразить его в средстве просмотра. Я предпочитаю, чтобы зритель открывался в новом окне, но я могу как-то встроить его в свою страницу.

Мне интересно, могу ли я напрямую передать blob или поток зрителю и отобразить документ. Я пробовал что-то вроде

PDFView.open(pdfAsArray, 0)

В этом случае во встроенном средстве просмотра ничего не происходит.

pdfAsArray хорош, так как я могу показать его добавление потока в холст на той же странице. Я просто хочу отобразить средство просмотра, а не вставлять PDF в холст, возможно, в новое окно.

Может ли кто-нибудь предоставить несколько строк кода о том, как добиться этого в Javascript?

4b9b3361

Ответ 1

Наконец-то я создал метод PDFView.open. Теперь, если я встрою средство просмотра в свою страницу и вызову функцию open, которую предложил Rob в первых двух примерах, он работает.

Для тех, кто ищет такое решение, я предоставляю несколько строк кода:

Это код в моей Lightswitch mainPage.lsml.js Сценарии js (pdf.js, viewer и другие) указаны на главной странице html проекта Lightswitch (Default.html); Я предполагаю, что он должен работать с любой другой html-страницей, не основанной на Lightswitch.

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

То, что все еще пропущено, - это возможность передать поток непосредственно на страницу viewer.html, чтобы открыть его в новом окне и иметь отдельный ui, где сделать рендеринг.

Этот код все еще не работает, так как я получил пустой просмотрщик без документа внутри

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) не передает зрителю хороший объект для загрузки в программу просмотра. Любая идея или предложение?

Ответ 2

Я использую 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 на элемент холста myCanvas.

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

Это показывает первую страницу pdf, но не имеет функциональности. Я вижу, почему зритель желателен. Если я подключу его к средству просмотра (viewer.html/viewer.js), я отредактирую свой ответ.

EDIT: как подключить зрителя

1 В bower.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>

3 Измените глупый документ по умолчанию в файле 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;
}

Ответ 3

Если у вас есть типизированный массив (например, 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);

Другой метод - создать URL-адрес объекта Blob/File:

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

Если средство просмотра PDF размещено в том же источнике, что и ваш веб-сайт, в который встроен фрейм, вы также можете просмотреть PDF, передав URL-адрес blob для просмотра:

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.

Ответ 4

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'