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?
Ответы
Ответ 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'