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?
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?
Share Improve this question edited Oct 25, 2018 at 9:02 kaizer1v 9088 silver badges21 bronze badges asked Mar 18, 2015 at 5:35 vesanvesan 3,36925 silver badges36 bronze badges 2- 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 Commented Mar 19, 2015 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 Commented Mar 19, 2015 at 22:06
2 Answers
Reset to default 3 +50Note, chromium / chrome browsers appear to append embed
element to document.body
to display .pdf
files
a) detecting
pdf
utilizingwindow.location.href
,document.querySelectorAll("embed")[0].type
;b) utilizing
XMLHttpRequest
to request existingdocument
, which should returnpdf
document
asblob
response, fromcache
; seeconsole
->Network
->Headers
->Status Code
To allow opening
file:
protocol
at chromium / chrome browsers, try utilizing mand 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();
};
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./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./p/chromium/issues/detail?id=169337.