Download PDF from cache for non-Firefox add-on

This feature relies on URL.createObjectURL, which is supported by
- Firefox 4
- Chrome 8
- Opera 15
- Internet Explorer 10

If the feature is missing, it falls back to downloading from the server.

The environment-specific code are put in ifdef's. Two methods are
defined:
- noData
  This function is used as a fallback in case of failure, it triggers
  a download directly from the server.
- triggerSaveAs(String url, optional String blob)
  This function attempts to show a Save As dialog for a given URL.
  It attempts to use the a.download attribute, if available, and
  falls back to window.open(<url>, '_parent') if unavailable.

See also http://caniuse.com/download
This commit is contained in:
Rob Wu 2013-07-02 17:15:32 +02:00
parent d71948038f
commit 4ffc408512

View File

@ -914,59 +914,55 @@ var PDFView = {
}, },
download: function pdfViewDownload() { download: function pdfViewDownload() {
function noData() {
FirefoxCom.request('download', { originalUrl: url });
}
var url = this.url.split('#')[0]; var url = this.url.split('#')[0];
//#if !(FIREFOX || MOZCENTRAL) //#if !(FIREFOX || MOZCENTRAL)
function noData() {
var a = document.createElement('a'); triggerSaveAs(url + '#pdfjs.action=download');
// If _parent == self, then opening an identical URL with different
// location hash will only cause a navigation, not a download.
if (window.top === window && !('download' in a) &&
url === window.location.href.split('#')[0]) {
url += url.indexOf('?') === -1 ? '?' : '&';
} }
function triggerSaveAs(url, blobUrl) {
// If blobUrl is not specified, fall back to non-blob url.
if (!blobUrl) blobUrl = url;
url += '#pdfjs.action=download'; var a = document.createElement('a');
if (a.click) { if (a.click) {
// Use a.click() if available. Otherwise, Chrome might show // Use a.click() if available. Otherwise, Chrome might show
// "Unsafe JavaScript attempt to initiate a navigation change // "Unsafe JavaScript attempt to initiate a navigation change
// for frame with URL" and not open the PDF at all. // for frame with URL" and not open the PDF at all.
// Supported by (not mentioned = untested): // Supported by (not mentioned = untested):
// - Firefox 6 - 19 (4- does not support a.click, 5 ignores a.click) // - Firefox 6 - 19 (4- does not support a.click, 5 ignores a.click)
// - Chrome 19 - 26 (18- does not support a.click) // - Chrome 19 - 26 (18- does not support a.click)
// - Opera 9 - 12.15 // - Opera 9 - 12.15
// - Internet Explorer 6 - 10 // - Internet Explorer 6 - 10
// - Safari 6 (5.1- does not support a.click) // - Safari 6 (5.1- does not support a.click)
a.href = url; a.href = blobUrl;
a.target = '_parent'; a.target = '_parent';
// Use a.download if available. This increases the likelihood that // Use a.download if available. This increases the likelihood that
// the file is downloaded instead of opened by another PDF plugin. // the file is downloaded instead of opened by another PDF plugin.
if ('download' in a) { if ('download' in a) {
var filename = url.match(/([^\/?#=]+\.pdf)/i); var filename = url.match(/([^\/?#=]+\.pdf\b)(?!.*\.pdf\b)/i);
a.download = filename ? filename[1] : 'file.pdf'; a.download = filename ? filename[1] : 'document.pdf';
}
// <a> must be in the document for IE and recent Firefox versions.
// (otherwise .click() is ignored)
(document.body || document.documentElement).appendChild(a);
a.click();
a.parentNode.removeChild(a);
} else {
if (window.top === window &&
blobUrl.split('#')[0] === window.location.href.split('#')[0]) {
// If _parent == self, then opening an identical URL with different
// location hash will only cause a navigation, not a download.
var padCharacter = blobUrl.indexOf('?') === -1 ? '?' : '&';
blobUrl = blobUrl.replace(/#|$/, padCharacter + '$&');
}
window.open(blobUrl, '_parent');
} }
// <a> must be in the document for IE and recent Firefox versions.
// (otherwise .click() is ignored)
(document.body || document.documentElement).appendChild(a);
a.click();
a.parentNode.removeChild(a);
} else {
window.open(url, '_parent');
} }
//#else //#else
// // Document isn't ready just try to download with the url. // function noData() {
// if (!this.pdfDocument) { // FirefoxCom.request('download', { originalUrl: url });
// noData();
// return;
// } // }
// this.pdfDocument.getData().then( // function triggerSaveAs(url, blobUrl) {
// function getDataSuccess(data) {
// var blob = PDFJS.createBlob(data.buffer, 'application/pdf');
// var blobUrl = window.URL.createObjectURL(blob);
//
// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url }, // FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
// function response(err) { // function response(err) {
// if (err) { // if (err) {
@ -977,10 +973,23 @@ var PDFView = {
// window.URL.revokeObjectURL(blobUrl); // window.URL.revokeObjectURL(blobUrl);
// } // }
// ); // );
// }, // }
// noData // Error occurred try downloading with just the url.
// );
//#endif //#endif
var URL = window.URL || window.webkitURL;
// If the PDF is not ready yet, or if createObjectURL is not supported,
// just try to download with the url.
if (!this.pdfDocument || !URL) {
noData();
return;
}
this.pdfDocument.getData().then(
function getDataSuccess(data) {
var blob = PDFJS.createBlob(data.buffer, 'application/pdf');
var blobUrl = URL.createObjectURL(blob);
triggerSaveAs(url, blobUrl);
},
noData // Error occurred try downloading with just the url.
);
}, },
fallback: function pdfViewFallback() { fallback: function pdfViewFallback() {