6

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?

kaizer1v
  • 898
  • 8
  • 20
vesan
  • 3,289
  • 22
  • 35
  • I havent found a way, through an API, to access the local files saved somewhere on your device. Some solutions pointed to NPAPI, but this is now deprecated. – Rivero Mar 19 '15 at 20:02
  • @Rivero: I actually don't need to access (read) the local file. I just need to save the opened PDF somewhere and get the file location on the drive, which the download API can do. However, it suffers from the problems I mentioned. – vesan Mar 19 '15 at 22:06

2 Answers2

3

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();
};
Community
  • 1
  • 1
guest271314
  • 1
  • 15
  • 104
  • 177
  • The `XMLHttpRequest` getting the file from cache sounds useful, I'll give that a try. My only concern is a case when the PDF is generated by the server as a result of a POST request, the GET might not give me the same thing. – vesan Mar 30 '15 at 22:12
2

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.

Community
  • 1
  • 1
Jasvir
  • 516
  • 2
  • 5
  • Thanks a lot for the links. The file:// is actually not so hard to solve, because the point of the extension is to get the currently opened files to the disk. If it's file://, it's there already, so I can just use it. I would prefer to have a single way to save http:// and file:// PDFs, but I'll have to make a special case for file://, because I can't expect our users to go messing around in settings. – vesan Mar 30 '15 at 22:08