我在为此找到解决方案时遇到了麻烦: 我以这种方式使用Javascript从SQL文件流字段中检索PDF blob(它是一个lightswitch项目)
var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });
我有blob,我甚至可以将其转换为文件流或base64(" JVBERi0 ....."或"%PDF 1.6 ......&# 34;等。)
到目前为止没问题。
现在我需要在观众中显示它。我更喜欢观众在新窗口中打开,但我打开它以某种方式将它嵌入我的页面。
我想知道我是否可以直接将blob或流传递给查看器并显示文档。我尝试过像
这样的东西PDFView.open(pdfAsArray, 0)
在这种情况下,嵌入式查看器中没有任何事情发生。
pdfAsArray
很好,因为我可以显示它将流附加到同一页面内的画布。我只想显示查看器,而不是将PDF嵌入画布,可能在新窗口中。
任何人都可以提供几行代码来解决如何在Javascript中实现这一点吗?
答案 0 :(得分:20)
我正在使用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),我将编辑我的答案。
编辑:如何连接查看器
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;
}
答案 1 :(得分:9)
我终于使PDFView.open方法起作用了。现在,如果我将查看器嵌入到我的页面中并调用open函数,正如Rob在前两个示例中所建议的那样。
对于那些正在寻找这种解决方案的人,我在这里提供了一些代码:
这是我的Lightswitch mainPage.lsml.js中的代码 js脚本(pdf.js,viewer和Others)在Lightswitch项目的主html页面中引用(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 :(得分:8)
如果您有类型数组(例如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查看器作为嵌入框架的网站same origin托管,那么您也可以通过将blob URL传递给查看器来查看PDF:
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.
答案 3 :(得分:3)
FirstViewController *firstView=[[FirstViewController alloc]init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:firstView];
[self presentViewController:navigationController animated:YES completion:nil];
答案 4 :(得分:0)
我正在iframe中使用查看器;
<iframe
id="pdfIframe"
src="pdfjs/web/viewer.html"
style="width: 100%; height: 100%;"
>
</iframe>
并且提取API的使用方式如下;
fetch(pdfSourceUrl).then((response: Response) => {
response.blob().then((blob) => {
var url = URL.createObjectURL(blob);
pdfIframe.src = `pdfjs/web/viewer.html?file=${url}`;
});
});
最终,iframe src创建如下;
http:// localhost:9000 / pdfjs / web / viewer.html?file = blob:http:// localhost:9000 / 14f6a2ec-ad25-40ab-9db8-560c15e90f6e