Download data URL file

JavascriptData Uri

Javascript Problem Overview


I'm playing with the idea of making a completely JavaScript-based zip/unzip utility that anyone can access from a browser. They can just drag their zip directly into the browser and it'll let them download all the files within. They can also create new zip files by dragging individual files in.

I know it'd be better to do it serverside, but this project is just for a bit of fun.

Dragging files into the browser should be easy enough if I take advantage of the various methods available. (Gmail style)

Encoding/decoding should hopefully be fine. I've seen some as3 zip libraries so I'm sure I should be fine with that.

My issue is downloading the files at the end.

window.location = 'data:jpg/image;base64,/9j/4AAQSkZJR....' 

this works fine in Firefox but not in Chrome.

I can embed the files as images just fine in chrome using <img src="data:jpg/image;ba.." />, but the files won't necessarily be images. They could be any format.

Can anyone think of another solution or some kind of workaround?

Javascript Solutions


Solution 1 - Javascript

If you also want to give a suggested name to the file (instead of the default 'download') you can use the following in Chrome, Firefox and some IE versions:

function downloadURI(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  delete link;
}

And the following example shows it's use:

downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");

Solution 2 - Javascript

function download(dataurl, filename) {
  const link = document.createElement("a");
  link.href = dataurl;
  link.download = filename;
  link.click();
}

download("data:text/html,HelloWorld!", "helloWorld.txt");

or:

function download(url, filename) {
  fetch(url)
    .then(response => response.blob())
    .then(blob => {
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = filename;
      link.click();
  })
  .catch(console.error);
}

download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");

Solution 3 - Javascript

Ideas:

  • Try a <a href="data:...." target="_blank"> (Untested)

  • Use downloadify instead of data URLs (would work for IE as well)

Solution 4 - Javascript

Want to share my experience and help someone stuck on the downloads not working in Firefox and updated answer to 2014. The below snippet will work in both firefox and chrome and it will accept a filename:

  // Construct the <a> element
  var link = document.createElement("a");
  link.download = thefilename;
  // Construct the uri
  var uri = 'data:text/csv;charset=utf-8;base64,' + someb64data
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  // Cleanup the DOM
  document.body.removeChild(link);

Solution 5 - Javascript

Here is a pure JavaScript solution I tested working in Firefox and Chrome but not in Internet Explorer:

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
	link.href = dataUrl;
    document.body.appendChild(link);
	link.click();

    // Cleanup the DOM
	document.body.removeChild(link);
    delete link;
}

Cross-browser solutions found up until now:

downloadify -> Requires Flash

databounce -> Tested in IE 10 and 11, and doesn't work for me. Requires a servlet and some customization. (Incorrectly detects navigator. I had to set IE in compatibility mode to test, default charset in servlet, JavaScript options object with correct servlet path for absolute paths...) For non-IE browsers, it opens the file in the same window.

download.js -> http://danml.com/download.html Another library similar but not tested. Claims to be pure JavaScript, not requiring servlet nor Flash, but doesn't work on IE <= 9.

Solution 6 - Javascript

There are several solutions but they depend on HTML5 and haven't been implemented completely in some browsers yet. Examples below were tested in Chrome and Firefox (partly works).

  1. Canvas example with save to file support. Just set your document.location.href to the data URI.
  2. Anchor download example. It uses <a href="your-data-uri" download="filename.txt"> to specify file name.

Solution 7 - Javascript

Combining answers from @owencm and @Chazt3n, this function will allow download of text from IE11, Firefox, and Chrome. (Sorry, I don't have access to Safari or Opera, but please add a comment if you try and it works.)

initiate_user_download = function(file_name, mime_type, text) {
    // Anything but IE works here
    if (undefined === window.navigator.msSaveOrOpenBlob) {
        var e = document.createElement('a');
        var href = 'data:' + mime_type + ';charset=utf-8,' + encodeURIComponent(text);
        e.setAttribute('href', href);
        e.setAttribute('download', file_name);
        document.body.appendChild(e);
        e.click();
        document.body.removeChild(e);
    }
    // IE-specific code
    else {
        var charCodeArr = new Array(text.length);
        for (var i = 0; i < text.length; ++i) {
            var charCode = text.charCodeAt(i);
            charCodeArr[i] = charCode;
        }
        var blob = new Blob([new Uint8Array(charCodeArr)], {type: mime_type});
        window.navigator.msSaveOrOpenBlob(blob, file_name);
    }
}

// Example:
initiate_user_download('data.csv', 'text/csv', 'Sample,Data,Here\n1,2,3\n');

Solution 8 - Javascript

This can be solved 100% entirely with HTML alone. Just set the href attribute to "data:(mimetypeheader),(url)". For instance...

<a
    href="data:video/mp4,http://www.example.com/video.mp4"
    target="_blank"
    download="video.mp4"
>Download Video</a>

Working example: JSFiddle Demo.

Because we use a Data URL, we are allowed to set the mimetype which indicates the type of data to download. Documentation:

>Data URLs are composed of four parts: a prefix (data:), a MIME type indicating the type of data, an optional base64 token if non-textual, and the data itself. (Source: MDN Web Docs: Data URLs.)

Components:

  • <a ...> : The link tag.

  • href="data:video/mp4,http://www.example.com/video.mp4" : Here we are setting the link to the a data: with a header preconfigured to video/mp4. This is followed by the header mimetype. I.E., for a .txt file, it would would be text/plain. And then a comma separates it from the link we want to download.

  • target="_blank" : This indicates a new tab should be opened, it's not essential, but it helps guide the browser to the desired behavior.

  • download: This is the name of the file you're downloading.

Solution 9 - Javascript

If you only need to actually have a download action, like if you bind it to some button that will generate the URL on the fly when clicked (in Vue or React for example), you can do something as easy as this:

const link = document.createElement('a')
link.href = url
link.click()

In my case, the file is already properly named but you can set it thanks to filename if needed.

Solution 10 - Javascript

For anyone having issues in IE:

Please upvote the answer here by Yetti: https://stackoverflow.com/questions/15931341/saving-canvas-locally-in-ie

dataURItoBlob = function(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

var blob = dataURItoBlob(uri);
window.navigator.msSaveOrOpenBlob(blob, "my-image.png");

Solution 11 - Javascript

Your problem essentially boils down to "not all browsers will support this".

You could try a workaround and serve the unzipped files from a Flash object, but then you'd lose the JS-only purity (anyway, I'm not sure whether you currently can "drag files into browser" without some sort of Flash workaround - is that a HTML5 feature maybe?)

Solution 12 - Javascript

export const downloadAs = async (url: string, name: string) => {
  const blob = await axios.get(url, {
    headers: {
      'Content-Type': 'application/octet-stream',
    },
    responseType: 'blob',
  });
  const a = document.createElement('a');
  const href = window.URL.createObjectURL(blob.data);
  a.href = href;
  a.download = name;
  a.click();
};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMikeeView Question on Stackoverflow
Solution 1 - JavascriptowencmView Answer on Stackoverflow
Solution 2 - JavascriptZibriView Answer on Stackoverflow
Solution 3 - JavascriptPekkaView Answer on Stackoverflow
Solution 4 - JavascriptMartino DinoView Answer on Stackoverflow
Solution 5 - JavascriptJesus M CView Answer on Stackoverflow
Solution 6 - JavascriptViacheslav DobromyslovView Answer on Stackoverflow
Solution 7 - JavascriptkevinarpeView Answer on Stackoverflow
Solution 8 - JavascriptHoldOffHungerView Answer on Stackoverflow
Solution 9 - JavascriptkissuView Answer on Stackoverflow
Solution 10 - JavascriptChazt3nView Answer on Stackoverflow
Solution 11 - JavascriptPiskvor left the buildingView Answer on Stackoverflow
Solution 12 - Javascriptuser1929437View Answer on Stackoverflow