I'm trying to print a PDF from the server. If a server error occurs, I want to display this error in the UI, for this, I try to use the onError handler, but it does not work, my function is not called.
printJS({
printable: "docs/myFile.pdf",
type: 'pdf',
showModal: true,
onError: err => console.log("Erorr") // it doesn't work
});
What am I doing wrong?
Hi @yaroslav-perec, your code should work as is.
Take a look at this fiddle. When I pass an invalid PDF document url, I'm able to catch and handle the error using the onError parameter.
https://jsfiddle.net/crabbly/1hpvsw2b/
Which browser and OS version have you tested this?
Thx.
Hi @crabbly, thanks for your reply. I'm using printJS in an Angular project.
Browser version: Google Chrome 70.0.3538.77
OS version: Ubuntu 18.04.1 LTS
Angular version: 7
I can't test this in Ubuntu. Browserstack doesn't support it. :(
Have you tried the fiddle above? Does it work?
Also, did you check the console for any errors?
Yes, fiddle above works.
I have this issue #244, but for testing, I added the missing parameters myself, as in this commit a50a41d.
In the console I have 400 Bad Request Error and this warning: Resource interpreted as Document but transferred with MIME type application/pdf: "blob:http://localhost:3000/547ea4ed-7d0e-490e-8188-b41ee0a36e0c". print.js:963
@crabbly
I understood what is the problem. When I use showModal: true, onError handler doesn't work, without this option, it works correctly. Can you check this behavior?
Good catch. There is no error handling in pdf.js. When we use showModal: true, the library will preload the remote pdf into a local blob, however, we don't check for any errors there. The code will keep running and the library will print the empty local blob.
We will need to implement something there, to handle the error and stop the print process (preventing the blank page / preview).
In my case when I use showModal: true, I don't have a preview with a blank page. When I start "printing", I have a modal window with the message "Retrieving Document", and when an error occurs, the modal window closes and nothing else.
@crabbly
The same problem if I use onLoadingStart and onLoadingEnd, onError handler doesn't work
printJS({
printable: 'docs/myFile.pdf',
type: 'pdf',
onLoadingStart: () => this.spinner.show(),
onLoadingEnd: () => this.spinner.hide(),
onError: err => console.log(err) // doesn't work
});
Hi @crabbly @yaroslav-perec
I may have a fix for you as I've had the same issue. Basically in pdf.js if you check that the specified URL exists first and encapsulate the rest of the method in a try clause, you can then set params.onError to trigger. Here is some code:
function UrlExists(url) {
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
if (!(http.status >= 200 && http.status < 300 || http.status === 304)) {
throw new Error(http.statusText);
}
}
`exports.default = {
print: function print(params, printFrame) {
// Format pdf url
params.printable = /^(blob|http)/i.test(params.printable) ? params.printable : window.location.origin + (params.printable.charAt(0) !== '/' ? '/' + params.printable : params.printable);
try {
UrlExists(params.printable);
// If showing a loading modal or using a hook function, we will preload the pdf file
if (params.showModal || params.onLoadingStart) {
// Get the file through a http request
var req = new window.XMLHttpRequest();
req.responseType = 'arraybuffer';
req.addEventListener('load', function () {
// Pass response data to a blob and create a local object url
var localPdf = new window.Blob([req.response], { type: 'application/pdf' });
localPdf = window.URL.createObjectURL(localPdf);
// Pass the url to the printable parameter (replacing the original pdf file url)
// This will prevent a second request to the file (server) once the iframe loads
params.printable = localPdf;
send(params, printFrame);
});
req.open('GET', params.printable, true);
req.send();
} else {
send(params, printFrame);
}
} catch (e) {
params.onError(e);
}
}
};`
Also, I found an issue with the modal appearing after the error message appears (this is at the point where the script checks for the printable type) - this also needs to be encapsulated in a try clause:
// Check printable type
switch (params.type) {
case 'pdf':
// Check browser support for pdf and if not supported we will just open the pdf file instead
if (_browser2.default.isFirefox() || _browser2.default.isEdge() || _browser2.default.isIE()) {
try {
console.info('PrintJS currently doesn\'t support PDF printing in Firefox, Internet Explorer and Edge.');
var win = window.open(params.fallbackPrintable, '_blank');
win.focus();
if (params.onPdfOpen) params.onPdfOpen();
} catch (e) {
params.onError(e);
} finally {
// Make sure there is no loading modal opened
if (params.showModal) _modal2.default.close();
if (params.onLoadingEnd) params.onLoadingEnd();
}
} else {
try {
_pdf2.default.print(params, printFrame);
} catch (e) {
params.onError(e);
} finally {
// Make sure there is no loading modal opened
if (params.showModal) _modal2.default.close();
if (params.onLoadingEnd) params.onLoadingEnd();
}
}
break;
case 'image':
_image2.default.print(params, printFrame);
break;
case 'html':
_html2.default.print(params, printFrame);
break;
case 'json':
_json2.default.print(params, printFrame);
break;
}
I hope this helps with your next version and to anyone else wanting to solve this issue!
Cheers
@harpsicord86 Cool! Thank you, Steve. We definitely need to fix this for the next release.
I just pushed a new commit to improve error handling. It will respect the onError parameter and stop code execution, preventing blank print jobs.
https://github.com/crabbly/Print.js/commit/ef66f4614049c812d927b420bfb0ae7bfa3013bf
@harpsicord86 Steve, I'm just checking for http status code 200 on this solution. We should add 201 as well, but I'm not sure about any other status code. I see that you used all the 200's in the comment above, but some may not make sense when it comes to a file / document request.
What do you think?
Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#Successful_responses
I added 201 as well. Will go ahead and run with these two for now.
https://github.com/crabbly/Print.js/commit/317bc847e2ebbb1c21ecd4cbbe06cebfc0b464b1
I'll be releasing this soon. Thank you.
Hi Rodrigo @crabbly I agree with your suggestion 馃憤 looking forward to the new version!
Hey guys, this change is now available with the latest version.
Run npm update print-js to get it.
Let me know of any issues. Thank you.