Chrome extension: How to save a file on disk
Asked Answered
B

7

93

I'm currently creating an extension for google chrome which can save all images or links to images on the harddrive.

The problem is I don't know how to save file on disk with JS or with Google Chrome Extension API.

Have you got an idea ?

Brandenburg answered 28/1, 2010 at 11:5 Comment(0)
B
46

You can use HTML5 FileSystem features to write to disk using the Download API. That is the only way to download files to disk and it is limited.

You could take a look at NPAPI plugin. Another way to do what you need is simply send a request to an external website via XHR POST and then another GET request to retrieve the file back which will appear as a save file dialog.

For example, for my browser extension My Hangouts I created a utility to download a photo from HTML5 Canvas directly to disk. You can take a look at the code here capture_gallery_downloader.js the code that does that is:

var url = window.webkitURL || window.URL || window.mozURL || window.msURL;
var a = document.createElement('a');
a.download = 'MyHangouts-MomentCapture.jpg';
a.href = url.createObjectURL(dataURIToBlob(data.active, 'jpg'));
a.textContent = 'Click here to download!';
a.dataset.downloadurl = ['jpg', a.download, a.href].join(':');

If you would like the implementation of converting a URI to a Blob in HTML5 here is how I did it:

/**
 * Converts the Data Image URI to a Blob.
 *
 * @param {string} dataURI base64 data image URI.
 * @param {string} mimetype the image mimetype.
 */
var dataURIToBlob = function(dataURI, mimetype) {
  var BASE64_MARKER = ';base64,';
  var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
  var base64 = dataURI.substring(base64Index);
  var raw = window.atob(base64);
  var rawLength = raw.length;
  var uInt8Array = new Uint8Array(rawLength);

  for (var i = 0; i < rawLength; ++i) {
    uInt8Array[i] = raw.charCodeAt(i);
  }

  var bb = new this.BlobBuilder();
  bb.append(uInt8Array.buffer);
  return bb.getBlob(mimetype);
};

Then after the user clicks on the download button, it will use the "download" HTML5 File API to download the blob URI into a file.

Behan answered 28/1, 2010 at 21:24 Comment(4)
It's not the first time we are redirecting me on the NPAPI. I will take a look at it. Thank you for your helpBrandenburg
Note that if you plan to upload the extension to Google's gallery, using NPAPI will delay your publishing for a long review by them and it may even not end up accepted.Woolridge
I agree with Max. It will delay publishing since it will be manually reviewed. It would be best if you have an external server that you can give access within your extension and upload the data via POST and fetch it back via GET with proper headers.Behan
Does it allow me to save a short marked word to the file on local hard disk?Equipoise
S
34

I had long been wishing to make a chrome extension for myself to batch download images. Yet every time I got frustrated because the only seemingly applicable option is NPAPI, which both chrome and firefox seem to have not desire in supporting any longer.

I suggest those who still wanted to implement 'save-file-on-disk' functionality to have a look at this Stackoverflow post, the comment below this post help me a lot.

Now since chrome 31+, the chrome.downloads API became stable. We can use it to programmatically download file. If the user didn't set the ask me before every download advance option in chrome setting, we can save file without prompting user to confirm!

Here is what I use (at extension's background page):

    // remember to add "permissions": ["downloads"] to manifest.json
    // this snippet is inside a onMessage() listener function
    var imgurl = "https://www.google.com.hk/images/srpr/logo11w.png";
    chrome.downloads.download({url:imgurl},function(downloadId){
        console.log("download begin, the downId is:" + downloadId);
    });

Though it's a pity that chrome still doesn't provide an Event when the download completes.chrome.downloads.download's callback function is called when the download begin successfully (not on completed)

The Official documentation about chrome.downloadsis here.

It's not my original idea about the solution, but I posted here hoping that it may be of some use to someone.

Snafu answered 1/3, 2014 at 10:50 Comment(3)
Don't know about 2014 but as of today it's possible to listen to the onChanged event which bears the state object that can tell the status of the download (e.g. "complete").Concrescence
@Allan, Re "we can save file without prompting user to confirm"; But wouldn't the "download bar" at the bottom be opened when you start writing files to the user's machine? Is there any way to do this silently? (For example, if you are writing 50 files to the user's machine in the background)Turnstone
@Turnstone it's call download shelf, when I wrote the answer, I remember I have to manually disable the shelf from showing in the advance options page. I do some search, I found this: you maybe interesting.setShelfEnabled chrome.downloads.setShelfEnabled(boolean enabled) Enable or disable the gray shelf at the bottom of every window associated with the current browser profile. The shelf will be disabled as long as at least one extension has disabled it. Enabling the shelf while at least one other extension has disabled it will return an error through runtime.lastError.Snafu
H
5

There's no way that I know of to silently save files to the user's drive, which is what it seems like you're hoping to do. I think you can ASK for files to be saved one at a time (prompting the user each time) using something like:

function saveAsMe (filename)
{
document.execCommand('SaveAs',null,filename)
}

If you wanted to only prompt the user once, you could grab all the images silently, zip them up in a bundle, then have the user download that. This might mean doing XmlHttpRequest on all the files, zipping them in Javascript, UPLOADING them to a staging area, and then asking the user if they would like to download the zip file. Sounds absurd, I know.

There are local storage options in the browser, but they are only for the developer's use, within the sandbox, as far as I know. (e.g. Gmail offline caching.) See recent announcements from Google like this one.

Hindbrain answered 28/1, 2010 at 18:41 Comment(0)
C
4

I made an extension that does something like this, if anyone here is still interested: GitHub

It uses an XMLHTTPRequest to grab the object, which in this case is presumed to be an image, then makes an ObjectURL to it, a link to that ObjectUrl, and clicks on the imaginary link.

Corriveau answered 10/8, 2012 at 4:14 Comment(1)
First link hits 404Caughey
C
3

Consider using the HTML5 FileSystem features that make writing to files possible using Javascript.

Callen answered 14/8, 2011 at 8:1 Comment(0)
S
3

Looks like reading and writing files from browsers has become possible. Some newer Chromium based browsers can use the "Native File System API". This 2020 blog post shows code examples of reading from and writing to the local file system with JavaScript.

https://blog.merzlabs.com/posts/native-file-system/

This link shows which browsers support the Native File System API.

https://caniuse.com/native-filesystem-api

Slattern answered 4/3, 2021 at 6:58 Comment(0)
A
0

Chrome offers a native chrome.fileSystem API which will let you do this without having to use html5 or send things only to the downloads folder.

See https://developer.chrome.com/docs/apps/reference/fileSystem for more

Amnion answered 2/4 at 15:13 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Lingam

© 2022 - 2024 — McMap. All rights reserved.