经过反复试验,我终于能够实现从 Windows 8 应用程序打印表示 PDF 二进制文件的 Base64 流。
我正在用 HTML / CSS / WinJS 编写应用程序。基本上这里是它是如何完成的简要说明:
在文件中创建一个新<canvas>
元素。default.html
将它放在元素的 open 标记之后。像这样:
<body role="application" class="app">
<canvas id="pdf-render-output"></canvas>
.
.
.
</body>
然后在default.css
文件中,设置一些规则以及打印媒体查询。像这样:
body > canvas {
display: none;
}
.
. /* all your app's default css styles */
.
@media print {
body > * {
display:none;
max-width: 100%;
}
html {
max-width: 100%;
border-top-color: none;
border-top: 0;
}
body > canvas {
display: block;
border: none;
max-width: 100%;
width: 100%;
height: 100%;
position: relative;
}
}
值得注意的是在 CSS 中声明规则的顺序。在声明默认 CSS 规则之后放置打印媒体查询很重要。
设置完成后,javascript 会处理其余部分。基本思想是将 PDF.js 输出渲染到 DOM 中的“隐藏”画布。当文档对象被发送到打印时,会查询 CSS 打印媒体声明,以便<body>
隐藏除 canvas 元素之外的所有元素。这是仅打印 PDF 第一页的 javascript:
//Define a container for the Base64 data we'll use with PDF.js
var pdfPrintData = {};
//Function to render PDF to canvas and begin printing contract with Windows 8 OS
printPrescription: function () {
var self = Application.navigator.pageControl,
printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
self.getPDF().done(function () {
var pdfStream = pdfPrintData.base64,
pdfFile = convertDataURIToBinary(pdfStream);
PDFJS.disableWorker = true;
PDFJS.getDocument(pdfFile).then(function (pdf) {
var numPages = pdf.numPages,
renderCanvas = $('#pdf-render-output')[0];
//setup canvas
renderCanvas.height = pdf.getPage(1).data.getViewport(1).height;
renderCanvas.width = pdf.getPage(1).data.getViewport(1).width;
//Setup a render context for pdf.js to out a pdf file to the canvas.
var renderContext = {
canvasContext: renderCanvas.getContext('2d'),
viewport: pdf.getPage(1).data.getViewport(1)
};
//Bring up Windows 8 OS print after PDF is rendered to render context.
pdf.getPage(1).data.render(renderContext).then(function () {
printManager.onprinttaskrequested = self.onPrintTaskRequested;
Windows.Graphics.Printing.PrintManager.showPrintUIAsync();
});
})
});
},
onPrintTaskRequested: function (e) {
var self = Application.navigator.pageControl,
printTask = e.request.createPrintTask("Print Prescription", function (args) {
args.setSource(MSApp.getHtmlPrintDocumentSource(document));
printTask.oncompleted = self.onPrintTaskCompleted;
});
},
onPrintTaskCompleted: function (e) {
if (e.completion === Windows.Graphics.Printing.PrintTaskCompletion.failed) {
console.log("[ERX] : Failed to print!");
}
}
该self.getPDF
方法只是一个检索 Base64 数据流的函数,并且该流被设置在.base64
全局pdfPrintData
对象的属性上。出于某种原因,我无法使用 pdf.js 将 pdf 渲染到动态创建的文档中的动态创建画布上。我必须将 pdf.js 渲染方法的输出渲染到 DOM 中已经存在的画布上。