I have a web application. It runs in Google Chrome and is not required to work in any other browser.
I have PDF data which has been generated on the server and sent back to the client in an AJAX request. I create a blob from the PDF data. I use window.URL.createObjectURL to create a URL from the blob, which I then load into a window (my preview_window) which has previously been created to show the PDF.
To load the URL, I set preview_window.location.href.
I would like to call revokeObjectURL to avoid wasting more and more resources as new PDFs are generated and previewed in the window. The problem is that calling it immediately after setting preview_window.location.href is too soon, and stops the PDF from being displayed. So I would like to call revokeObjectURL only once the URL has been loaded. I have tried setting preview_window.onload to a callback for this purpose, but it never gets called.
I would like to know:
- Is it possible to trigger a callback when the window has loaded the URL, as I am trying to do? How?
- Is there another approach to ensure revokeObjectURL gets called in a timely manner?
If I cannot trigger revokeObjectURL when the window finishes loading the URL, I may revoke each URL immediately before generating a new one. But I would rather revoke the URL as soon as it is done loading, if possible.
I have prepared a html file which demonstrates the situation pretty well:
<html>
<head>
<title>Show PDF Demo</title>
<script>
var build_blob = function(mime_type, data) {
var buf = new ArrayBuffer(data.length);
var ia = new Uint8Array(buf);
for (var i = 0; i < data.length; i++) ia[i] = data.charCodeAt(i);
var blob = new Blob([ buf ], { type: mime_type });
return blob;
};
window.onload = function(e) {
document.getElementById('preview_button').onclick = function(e) {
// open the window in the onclick handler so we don't trigger popup blocking
var preview_window = window.open(null, 'preview_window');
// use setTimeout to simulate an asynchronous AJAX request
setTimeout(function(e) {
var pdf_data = atob(
"JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2Vz" +
"IDMgMCBSCj4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBlIC9PdXRsaW5lcwovQ291bnQgMAo+Pgpl" +
"bmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZXMKL0tpZHMgWzQgMCBSXQovQ291bnQgMQo+Pgpl" +
"bmRvYmoKNCAwIG9iago8PCAvVHlwZSAvUGFnZQovUGFyZW50IDMgMCBSCi9NZWRpYUJveCBbMCAw" +
"IDUwMCAyMDBdCi9Db250ZW50cyA1IDAgUgovUmVzb3VyY2VzIDw8IC9Qcm9jU2V0IDYgMCBSCi9G" +
"b250IDw8IC9GMSA3IDAgUiA+Pgo+Pgo+PgplbmRvYmoKNSAwIG9iago8PCAvTGVuZ3RoIDczID4+" +
"CnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDEwMCBUZAooU01BTEwgVEVTVCBQREYgRklMRSkgVGoK" +
"RVQKZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqClsvUERGIC9UZXh0XQplbmRvYmoKNyAwIG9iago8" +
"PCAvVHlwZSAvRm9udAovU3VidHlwZSAvVHlwZTEKL05hbWUgL0YxCi9CYXNlRm9udCAvSGVsdmV0" +
"aWNhCi9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+PgplbmRvYmoKeHJlZgowIDgKMDAwMDAw" +
"MDAwMCA2NTUzNSBmCjAwMDAwMDAwMDkgMDAwMDAgbgowMDAwMDAwMDc0IDAwMDAwIG4KMDAwMDAw" +
"MDEyMCAwMDAwMCBuCjAwMDAwMDAxNzkgMDAwMDAgbgowMDAwMDAwMzY0IDAwMDAwIG4KMDAwMDAw" +
"MDQ2NiAwMDAwMCBuCjAwMDAwMDA0OTYgMDAwMDAgbgp0cmFpbGVyCjw8IC9TaXplIDgKL1Jvb3Qg" +
"MSAwIFIKPj4Kc3RhcnR4cmVmCjYyNQolJUVPRg=="
);
/*
Warning: for my Chrome (Version 44.0.2403.155 m), the in-built PDF viewer doesn't seem
to work with a blob when this html page is loaded from the local filesystem. I have only
got this to work when fetching this page via HTTP.
*/
var pdf_blob = build_blob('application/pdf', pdf_data);
var pdf_url = window.URL.createObjectURL(pdf_blob);
preview_window.onload = function(e) {
console.log("preview_window.onload called"); // never happens
window.URL.revokeObjectURL(pdf_url);
};
preview_window.location.href = pdf_url;
console.log("preview_window.location.href set");
}, 500);
};
};
</script>
</head>
<body>
<button id="preview_button">Show Preview</button>
</body>
</html>
Although my demo code above avoids it, I do have jQuery loaded for my application, so if that makes things easier I'm open to using it.
I did find this question in a search, but in that situation the main window ("window") is pointed to a new URL, and the OP never got a response when asking in comments whether it makes a difference if the window came from window.open.