问题
I am working on a Windows 8 Javascript application that generates a PDF using PDFKit.
Normally you'd make a blobstream using pipe and then make an URL of it that you send to the browser. This only works if the website is run from a server, which is not the case since it's a local app. However I do have access to the file system and I'd like to save the generated PDF to a file.
To do this I was inspired by this question: How to pipe a stream using pdfkit with node js
I tried both above's solutions using Browserify, replacing the printer code with code that saves to a file:
Windows.Storage.ApplicationData.current.localFolder.createFileAsync("test.pdf",
Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
//write as text
Windows.Storage.FileIO.writeTextAsync(file, data).then(function () {});
//or write as buffer
var buffUTF8 = Windows.Security.Cryptography.CryptographicBuffer.convertStringToBinary(data, 0);
Windows.Storage.FileIO.writeBufferAsync(file, buffUTF8).then(function () {});
});
As you can see I both tried using writing as text or writing as a buffer, both gave me exactly the same files.
The PDF file is created but when I open it it shows a blank page. If I open the pdf in a text editor and compare it to a valid PDF I can tell that the stream part of the file has different kind of characters.
Also the Visual Studio output window is spamming me with Javascript run-time error messages about the URI having invalid encoding.
So it's obviously an encoding issue and I'm not sure what to do next. Any tips on how to save a PDFkit document to a file?
回答1:
I took a different approach and found out that base64 is the way to go. This way I didn't get it just to work in Windows but on other platforms like OSX as well.
The key was to use blob-stream.js and a FileReader object to convert a Blob object to a data url (which is basically base64).
<script src="/pdfkit.js"></script>
<script src="/blob-stream.js"></script>
For Windows you then convert the base64 to an IBuffer object and save that to file. Below shows an example, the part after var base64 is specific for Windows but it works similar on other platforms:
var doc = new PDFDocument({ size: 'A4', layout: 'portrait' });
stream = doc.pipe(blobStream());
stream.on('finish', function () {
fileReader = new FileReader();
fileReader.onload = function () {
//get base64 part of the data url
var base64 = fileReader.result.substr(fileReader.result.indexOf(',') + 1);
//create file, create IBuffer, save and launch pdf reader
Windows.Storage.ApplicationData.current.temporaryFolder.createFileAsync("test.pdf", Windows.Storage.CreationCollisionOption.generateUniqueName).then(function (file) {
var buffUTF8 = Windows.Security.Cryptography.CryptographicBuffer.decodeFromBase64String(base64);
Windows.Storage.FileIO.writeBufferAsync(file, buffUTF8).then(function () {
Windows.System.Launcher.launchFileAsync(file);
});
});
};
fileReader.onerror = function () {
console.log('error loading file');
};
fileReader.readAsDataURL(stream.toBlob('application/pdf'));
});
//draw PDF content here
doc.text('Hello World!', 100, 100);
doc.end();
回答2:
This is working for me in firefox
_downloadAsPdf: (data) =>
doc = new PDFDocument()
imgData = @renderer.canvas.toDataURL('image/png')
stream = doc.pipe(blobStream())
doc.image(imgData)
doc.end()
stream.on 'finish', ->
blob = stream.toBlob('application/pdf')
# save as file
date = new Date()
time = date.toLocaleTimeString()
pageNum = data.pageNumber
fileName = "page" + pageNum + "_" + time + ".pdf"
saveAs(blob, fileName)
回答3:
A cross-browser solution that works for me: set the data-URL you generate from the PDF as the source for a temporary link element:
function data_url_to_download(data_url, filename) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none;";
a.href = data_url;
a.download = filename;
a.click();
a.remove();
};
The file can then be downloaded automatically when the PDF generation is complete:
// Generate document to a stream with PDFKit, then...
stream.on("finish", function() {
data_url_to_download(stream.toBlobURL("application/pdf"), "output.pdf");
});
来源:https://stackoverflow.com/questions/30965249/pdfkit-js-how-to-save-document-to-file-win-8-app