Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome extension - saving PDF file

I'm developing a Chrome extension that will save files to the downloads folder (that's not all it's doing, but that's the part I have trouble with). Right now I'm focusing on PDF files. Basically, when a PDF is opened in Chrome, the user can manually save it using Menu -> Save File As ..., I'm just trying to automate this functionality using the extension, but I haven't found a good way to do it.

Let's say I can detect if the current tab has a PDF file in it (based on answers from this question).

The best thing I have figured out so far is to initiate a download:

chrome.downloads.download({
    url: tabs[0].url, saveAs: false,
    filename: "my file", /* This will be some unique autogenerated identifier */
    conflictAction: "overwrite"
});

This works but has 2 drawbacks:

  • The file has to be re-downloaded, which is a pain if it's large. Besides, the file has been downloaded already so I should be able to use it.
  • For some reason this doesn't work with files opened locally ("file://..."). It throws a NETWORK_INVALID_REQUEST and doesn't download.

Is there a better way to save the file?

like image 634
vesan Avatar asked Mar 18 '15 05:03

vesan


2 Answers

Note, chromium / chrome browsers appear to append embed element to document.body to display .pdf files

  1. a) detecting pdf utilizing window.location.href , document.querySelectorAll("embed")[0].type;

    b) utilizing XMLHttpRequest to request existing document, which should return pdf document as blob response, from cache; see console -> Network -> Headers -> Status Code

  2. To allow opening file: protocol at chromium / chrome browsers, try utilizing command line flag --allow-access-from-files; see How do I make the Google Chrome flag “--allow-file-access-from-files” permanent?


At .pdf document , i.e.g; Ecma-262.pdf try

// check if `document` is `pdf`
if (/pdf/i.test(window.location.href.slice(-3)) 
    || document.querySelectorAll("embed")[0].type === "application/pdf") {
    var xhr = new XMLHttpRequest();
    // load `document` from `cache`
    xhr.open("GET", "", true); 
    xhr.responseType = "blob";
    xhr.onload = function (e) {
        if (this.status === 200) {
            // `blob` response
            console.log(this.response);
            var file = window.URL.createObjectURL(this.response);
            var a = document.createElement("a");
            a.href = file;
            a.download = this.response.name 
                        || document.querySelectorAll("embed")[0].src
                           .split("/").pop();
            document.body.appendChild(a);
            a.click();
            // remove `a` following `Save As` dialog, 
            // `window` regains `focus`
            window.onfocus = function () {                     
                Array.prototype.forEach.call(document.querySelectorAll("a")
                , function (el) {
                    document.body.removeChild(el)
                })
            }
        };
    };
    xhr.send();
};
like image 116
guest271314 Avatar answered Nov 16 '22 21:11

guest271314


Addressing only the file:// aspect of your problem. Does your extension have permission to access file://. In order to have access your extension both needs to ask for file:/// and user has to manually grant this access from the extensions page. You can check if you have the requisite permission using https://developer.chrome.com/extensions/extension#method-isAllowedFileSchemeAccess.

See Adding file://. permission to chrome extension for more information about accessing file:// urls. You may also find How can I enable my chrome extension in incognito mode? helpful.

For a related discussion (although not specific for your use case since you already have a PDF file), also see https://code.google.com/p/chromium/issues/detail?id=169337.

like image 32
Jasvir Avatar answered Nov 16 '22 21:11

Jasvir