После проб и ошибок мне наконец удалось реализовать печать потока Base64, представляющего двоичный файл PDF из приложения Windows 8.
Я кодирую приложение в HTML/CSS/WinJS. По сути, вот краткое объяснение того, как это было достигнуто:
Создайте новый элемент <canvas>
в файле default.html
. Поместите его сразу после открытого тега элемента. Нравится:
<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>
были скрыты, кроме элемента холста. Вот javascript для печати только первой страницы в PDF:
//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-файл с помощью pdf.js для динамического создания холста в динамически создаваемом документе. Мне пришлось отображать вывод метода рендеринга pdf.js на холст, уже присутствующий в DOM.
11.07.2013