javascript - pdfjs - Pdf.js y viewer.js. Pasa un stream o blob al espectador
pdf.js viewer example (4)
Estoy usando PDFJS.version = ''1.0.1040''; PDFJS.build = ''997096f'';
PDFJS.version = ''1.0.1040''; PDFJS.build = ''997096f'';
El código que me funcionó para cargar los datos pdf base64 fue 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 función podría ser la función de éxito de una promesa de llamada api. Lo que estoy haciendo aquí es renderizar el pdf en un elemento de lienzo myCanvas
.
<canvas id="myCanvas"></canvas>
Esto muestra la primera página del pdf pero no tiene ninguna funcionalidad. Puedo ver por qué el espectador es deseable. Si me conecto al visor (viewer.html / viewer.js) editaré mi respuesta.
EDITAR: Cómo conectar al espectador
1 En bower.json
, agregue "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 Cambie el documento por defecto estúpido en el archivo 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;
}
Estoy teniendo problemas para encontrar una solución para esto: recupero un blob de PDF de un campo de secuencia de archivos SQL usando Javascript de esta manera (es un proyecto de interruptor de luz)
var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });
Tengo el blob e incluso puedo convertirlo en un flujo de archivos o en base64 ("JVBERi0 ....." o "% PDF 1.6 ......", etc.)
No hay problema hasta ahora.
Ahora necesito mostrarlo en un visor. Prefiero que el espectador se abra en una nueva ventana, pero estoy abierto para insertarlo en mi página de alguna manera.
Me pregunto si puedo pasar el blob o el flujo directamente al espectador y mostrar el documento. He intentado algo como
PDFView.open(pdfAsArray, 0)
Nada sucede en el visor incorporado en este caso.
El pdfAsArray
es bueno ya que puedo mostrarlo agregando el flujo a un lienzo dentro de la misma página. Solo quiero mostrar el visor, no incrustar el PDF en un lienzo, posiblemente en una nueva ventana.
¿Alguien puede proporcionar algunas líneas de código sobre cómo lograr eso en Javascript?
Finalmente hice el método PDFView.open funcionando. Ahora si inserto el visor en mi página y llamo a la función de abrir como Rob sugirió en los primeros 2 ejemplos, funciona.
Para aquellos que buscan este tipo de solución, proporciono algunas líneas de código aquí:
Este es el código en mi Lightswitch mainPage.lsml.js. Los scripts js (pdf.js, viewer y otros) están referenciados en la página principal html del proyecto Lightswitch (Default.html); Supongo que debería funcionar con cualquier otra página html que no esté basada en 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 es la función 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;
}
Lo que todavía se pierde es la posibilidad de pasar el flujo directamente a la página viewer.html para abrirlo en una nueva ventana y tener una interfaz de usuario separada donde realizar el renderizado.
Este código aún no funciona porque obtuve un visor vacío sin 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 el encodeURIComponent (url) no está pasando al espectador un buen objeto para cargar en el visor. ¿Alguna idea o sugerencia?
Si tiene una matriz escrita (por ejemplo, un Uint8Array
), entonces el archivo se puede abrir utilizando PDFView.open(typedarray, 0);
.
Si tienes un objeto Blob
o File
, entonces los datos deben convertirse a una matriz escrita antes de poder verlos:
var fr = new FileReader();
fr.onload = function() {
var arraybuffer = this.result;
var uint8array = new Uint8Array(arraybuffer);
PDFView.open(uint8array, 0);
};
fr.readAsArrayBuffer(blob);
Otro método es crear una URL para el objeto Blob / File:
var url = URL.createObjectURL(blob);
PDFView.open(url, 0);
Si el Visor de PDF está alojado en el mismo origen que su sitio web que incrusta el marco, también puede ver el PDF pasando la URL del blob al visor:
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''