Download data URL file

Viewed 532592

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?

13 Answers

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.

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.

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();
};

You can use a clean code solution, inform your url in a constant, and set it as param of open method instead in object window.

const url = "file url here"

window.open(url)

Related