Pdf.js e viewer.js. Passar um stream ou blob para o espectador

Eu estou tendo problemas em encontrar uma solução para isso: Eu recupero um blob PDF de um campo de stream de SQL usando Javascript desse jeito (é um projeto de lightswitch)

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

Eu tenho o blob e posso até convertê-lo em um stream de arquivos ou para base64 (“JVBERi0 …..” ou “% PDF 1.6 ……”, etc.)

Nenhum problema até agora.

Agora preciso exibi-lo em um visualizador. Eu prefiro que o espectador abra em uma nova janela, mas eu estou aberto para incorporá-lo na minha página de alguma forma.

Eu estou querendo saber se eu posso passar diretamente o blob ou o stream para o visualizador e exibir o documento. Eu tentei algo como

 PDFView.open(pdfAsArray, 0) 

Nada acontece no visualizador incorporado neste caso.

O pdfAsArray é bom, pois posso exibi-lo anexando o stream a uma canvas dentro da mesma página. Eu só quero exibir o visualizador, não incorporar o PDF em uma canvas, possivelmente em uma nova janela.

Alguém pode fornecer algumas linhas de código sobre como conseguir isso em JavaScript?

Estou usando o PDFJS.version = '1.0.1040'; PDFJS.build = '997096f'; PDFJS.version = '1.0.1040'; PDFJS.build = '997096f';

O código que funcionou para mim para obter dados de base64 pdf carregado foi este:

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

Esta function pode ser a function de sucesso de uma promise de chamada de API. O que estou fazendo aqui é renderizar o pdf em um elemento myCanvas canvas.

  

Isso mostra a primeira página do pdf, mas não tem funcionalidade. Eu posso ver porque o espectador é desejável. Se eu ficar ligado ao visualizador (viewer.html / viewer.js), eu vou editar minha resposta.

EDIT: Como ligar o visualizador

1 No bower.json , adicione "pdfjs-viewer": "1.0.1040"

2 Html:

  

3 Altere o documento padrão estúpido no arquivo viewer.js :

var DEFAULT_URL = '';

4 Controlador:

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

Eu finalmente fiz o método PDFView.open funcionando. Agora, se eu incorporar o visualizador na minha página e chamar a function aberta como Rob sugeriu nos dois primeiros exemplos, ele funciona.

Para aqueles que estão procurando por esse tipo de solução, forneço algumas linhas de código aqui:

Este é o código na minha Lightswitch mainPage.lsml.js Os scripts js (pdf.js, viewer e Others) são referenciados na página principal do projeto Lightswitch (Default.html); Eu suponho que deve funcionar com qualquer outra página html não baseada em 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 }; 

Esta é a function 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; } 

O que ainda falta é a possibilidade de passar o stream diretamente para a página viewer.html, a fim de abri-lo em uma nova janela e ter uma interface de usuário separada onde fazer a renderização.

Este código ainda não está funcionando desde que recebi um visualizador vazio sem nenhum documento dentro

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

Parece que o encodeURIComponent (url) não está transmitindo ao visualizador um bom object para carregar no visualizador. Alguma ideia ou sugestão?

Se você tem uma matriz tipada (por exemplo, um Uint8Array ), o arquivo pode ser aberto usando PDFView.open(typedarray, 0); .

Se você tiver um object Blob ou File , os dados deverão ser convertidos em uma matriz tipada antes que você possa exibi-los:

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

Outro método é criar um URL para o object Blob / File:

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

Se o PDF Viewer estiver hospedado na mesma origem do site que incorpora o quadro, você também poderá visualizar o PDF transmitindo o URL do blob ao visualizador:

 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. 
 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'