Is there any way to specify a suggested filename when using data: URI?

196,679

Solution 1

Use the download attribute:

<a download='FileName' href='your_url'>

The download attribute works on Chrome, Firefox, Edge, Opera, desktop Safari 10+, iOS Safari 13+, and not IE11.

Solution 2

Chrome makes this very simple these days:

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}

Solution 3

HTML only: use the download attribute:

<a download="logo.gif" href="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">Download transparent png</a>

Javascript only: you can save any data URI with this code:

function saveAs(uri, filename) {
  var link = document.createElement('a');
  if (typeof link.download === 'string') {
    link.href = uri;
    link.download = filename;

    //Firefox requires the link to be in the body
    document.body.appendChild(link);
    
    //simulate click
    link.click();

    //remove the link when done
    document.body.removeChild(link);
  } else {
    window.open(uri);
  }
}

var file = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
saveAs(file, 'logo.gif');

Chrome, Firefox, and Edge 13+ will use the specified filename.

IE11, Edge 12, and Safari 9 (which don't support the download attribute) will download the file with their default name or they will simply display it in a new tab, if it's of a supported file type: images, videos, audio files, …

Solution 4

According to RFC 2397, no, there isn't.

Nor does there appear to be any attribute of the <a> element that you can use either.

However HTML5 has subsequently introduced the download attribute on the <a> element, although at the time of writing support is not universal (no MSIE support, for example)

Solution 5

I've looked a bit in firefox sources in netwerk/protocol/data/nsDataHandler.cpp

data handler only parses content/type and charset, and looks if there is ";base64" in the string

the rfc specifices no filename and at least firefox handles no filename for it, the code generates a random name plus ".part"

I've also checked firefox log

[b2e140]: DOCSHELL 6e5ae00 InternalLoad data:application/octet-stream;base64,SGVsbG8=
[b2e140]: Found extension '' (filename is '', handling attachment: 0)
[b2e140]: HelperAppService::DoContent: mime 'application/octet-stream', extension ''
[b2e140]: Getting mimeinfo from type 'application/octet-stream' ext ''
[b2e140]: Extension lookup on '' found: 0x0
[b2e140]: Ext. lookup for '' found 0x0
[b2e140]: OS gave back 0x43609a0 - found: 0
[b2e140]: Searched extras (by type), rv 0x80004005
[b2e140]: MIME Info Summary: Type 'application/octet-stream', Primary Ext ''
[b2e140]: Type/Ext lookup found 0x43609a0

interesting files if you want to look at mozilla sources:

data uri handler: netwerk/protocol/data/nsDataHandler.cpp
where mozilla decides the filename: uriloader/exthandler/nsExternalHelperAppService.cpp
InternalLoad string in the log: docshell/base/nsDocShell.cpp

I think you can stop searching a solution for now, because I suspect there is none :)

as noticed in this thread html5 has download attribute, it works also on firefox 20 http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-download

Share:
196,679

Related videos on Youtube

tshepang
Author by

tshepang

I do software development for a living and as a hobby. My favorite language is Rust, and I've used Python much in the past. My OS of choice is Debian.

Updated on September 05, 2021

Comments

  • tshepang
    tshepang over 2 years

    If for example you follow the link:

    data:application/octet-stream;base64,SGVsbG8=

    The browser will prompt you to download a file consisting of the data held as base64 in the hyperlink itself. Is there any way of suggesting a default name in the markup? If not, is there a JavaScript solution?

    • Endless
      Endless over 8 years
      maybe unrelated to this issue but I suggest using blob's & URL.createObjectURL if this isn't an server or old browser obstacle
    • mems
      mems about 7 years
      Some browsers support the mediatype's optional parameter "name": data:application/pdf;name=document.pdf;base64,BASE64_DATA_EN‌​CODED
    • Bernhard
      Bernhard over 6 years
      I had the issue with Firefox pdf.js which tends to hang in some cases if it cannot extract a filename from the data uri. see stackoverflow.com/questions/45585921/…
    • TheAddonDepot
      TheAddonDepot over 5 years
      @mems Which browsers support the "name" parameter? Can you point me to some reference documentation? (my google-fu has failed me).
    • mems
      mems over 5 years
      @DimuDesigns At least Firefox at that time. It look like it's not anymore the case. It's related to MIME Content-Type (!= Content-Disposition) "name" parameter (not in RFC?)
    • LF00
      LF00 about 2 years
  • James Khoury
    James Khoury almost 13 years
    unfortunately this does not download.
  • Alnitak
    Alnitak almost 13 years
    this discussion was for a proposed extension to the data URI format - it hasn't been implemented.
  • Alnitak
    Alnitak almost 13 years
    The purpose of data: is to fudge a block of internal data into URL format without having to read it from a protocol-based source. The link in @silex's answer shows that the ability to suggest a preferred name to write it to is considered useful, even if it's not implemented yet.
  • Gleno
    Gleno almost 13 years
    Cool! Although I don't necessarily agree that Firefox is the ultimate authority on what exists. :)
  • Lightness Races in Orbit
    Lightness Races in Orbit almost 13 years
    @Alnitak: Useful? Absolutely. Technically appropriate? Still not convinced. :)
  • Alnitak
    Alnitak almost 13 years
    @Tomalak consider the difference between loading the data and saving it - just because a blob is encoded inline in a data: URL doesn't mean that it shouldn't have a preferred name for saving it to.
  • Lightness Races in Orbit
    Lightness Races in Orbit almost 13 years
    @Alnitak: The data itself should have no knowledge of how you load or save it. It's data.
  • jcolebrand
    jcolebrand almost 13 years
    This is not a solution and does not meet what was asked for. Sorry.
  • Alnitak
    Alnitak almost 13 years
    But your line about it's "entire purpose" is wrong. data: was specifically invented to allow (small) inline content to appear in a fudged-together URL format so that it could be used by things like image tags without a separate HTTP request. HTML says the content of a img src attribute must be a URL, so that's what RFC 2397 created. There is no "data source".
  • Lightness Races in Orbit
    Lightness Races in Orbit almost 13 years
    @Alnitak: Exactly. There's no data source. There's no context. The URI is the data.
  • Lightness Races in Orbit
    Lightness Races in Orbit almost 13 years
    Lol @ "minor user intervention". Getting the user to do the whole thing for you is not "minor user intervention".
  • Biovisualize
    Biovisualize over 12 years
    This answer is the only complete one. No you can't do it with data: URI. Yes you can provide a file name to a download link with pure Javascript. Thanks!
  • James Khoury
    James Khoury over 12 years
    Interesting script but it does require the server to get the response ans send it back right? jsfiddle.net/hZySf
  • Senseful
    Senseful over 12 years
    @BioDesign: It works even with data:URI's in chrome. See: jsfiddle.net/pYpqW
  • flying sheep
    flying sheep about 12 years
    the second sentence was right at the time of writing, but isn’t anymore. as of now, it isn’t yet widely implemented, though.
  • flying sheep
    flying sheep about 12 years
    but you can’t do it with window.location.replace. if you e.g. want to create a data:uri or one generated by window.URL.createObjectURL, and download that as file, you’ll have to create an <a> and click it: jsfiddle.net/flyingsheep/wpQtH (no, $(...).click() doesn’t work)
  • flying sheep
    flying sheep about 12 years
    see this comment for more info :)
  • orip
    orip over 11 years
    It's a WHATWG feature that Google implements, but since it's an (unofficial) standard it could get popular. whatwg.org/specs/web-apps/current-work/multipage/…
  • streetlight
    streetlight over 11 years
    Only if all browser were like Chrome... [sigh]
  • streetlight
    streetlight over 11 years
    I'm not sure where the file is being generated from.. is that file being stored in the base64 encode? (I'm not too familiar with base64)
  • Rob W
    Rob W over 11 years
    @flyingsheep $('<a href="data:text/plain,Test" download="test.txt">')[0].click() seems to work fine here (Chrome 23) (note: I used the native click method, not jQuery's one). Demo: jsfiddle.net/2zsRW
  • flying sheep
    flying sheep over 11 years
    but in firefox, only jsfiddle.net/2zsRW/1 works. maybe some sort of same-origin-policy or bug? (an aside: since the download attribute is not yet implemented, it just replaces the frame there instead of downloading)
  • Dan Lugg
    Dan Lugg over 11 years
    Implemented or not, with existing support for arbitrary parameters this would be a great.
  • Andrzej Doyle
    Andrzej Doyle over 11 years
    @streetlight: The "file" (i.e. data) is generated by Javascript. The context of that project (and probably most here) assume that you have some way of getting your desired data into a JS variable. The difference is that instead of presenting it to the user via a data:... URI, that script creates a form to POST it to the server. And the server then presumably echoes it straight back as an HTTP "download" response (i.e. with an appropriate Content-Disposition header specifying the filename).
  • Michael J. Calkins
    Michael J. Calkins over 10 years
    Idk what all these other answers are talking about this worked on first try in Chrome 30.
  • Holf
    Holf over 10 years
    It does now but it wasn't always so easy. Many of these answers are from years ago. And they also work for other browsers.
  • William Denniss
    William Denniss over 10 years
    @flyingsheep it seems they are enforcing a same-origin policy in Firefox "In Firefox 20 this attribute is only honored for links to resources with the same-origin." developer.mozilla.org/en-US/docs/Web/HTML/Element/a In my testing, Chrome doesn't have this limitation.
  • tixastronauta
    tixastronauta about 10 years
    Refer to http://caniuse.com/#feat=download for a complete list of browser compatibility.
  • p0lar_bear
    p0lar_bear about 10 years
    With jQuery 1.11 I get an exception because of the .remove(). I got around this by assigning $().appendTo() to a variable then calling variable.click(); variable.remove()
  • drzaus
    drzaus almost 10 years
    Combine this with stackoverflow.com/questions/17311645/… to trigger the generated link and you don't need user intervention. You can specify the HTML5 download attribute to suggest a name as mentioned by many other answers.
  • fregante
    fregante over 9 years
    This doesn't work in Firefox, I added an extended answer below with Fx compatibility.
  • fregante
    fregante over 9 years
    Both demos work fine for me in Chrome 38 (but they should work in Chrome 14+)
  • drzaus
    drzaus over 9 years
    @p0lar_bear you should get that exception with any jQuery, because getting the [0] from any "jQuery element" should return the first DOM element it represents, which essentially "takes you out of" jQuery.
  • drzaus
    drzaus over 9 years
    You actually shouldn't need to append/remove the element at all -- see comments at stackoverflow.com/a/17311705/1037948
  • tuomassalo
    tuomassalo about 9 years
    Interesting! Support seems to be quite shallow for now, though: caniuse.com/#feat=serviceworkers
  • Pacerier
    Pacerier about 9 years
    @flyingsheep, It is widely implemented.
  • jcolebrand
    jcolebrand about 9 years
    @Pacerier thank you for keeping the answer up to date, but when is the timespan of "currently"
  • flying sheep
    flying sheep about 9 years
    it wasn’t 3 years ago when i wrote that comment
  • Pacerier
    Pacerier about 9 years
    @jcolebrand, It's per the edited date which can be seen below the post. Btw where's the comment where you called me a jerk?
  • Sebastian Brosch
    Sebastian Brosch over 8 years
    pls add a more detailed explanation to your answer - stackoverflow.com/help/how-to-answer
  • Iulian Onofrei
    Iulian Onofrei about 8 years
    Is there any way to "respond" with another direct url to a file?
  • Luis A. Florit
    Luis A. Florit about 8 years
    @tixastronauta: Despite the info in that page, not working in my firefox 44. Working nicely in Chrome. 48
  • Fraccier
    Fraccier almost 8 years
    Hi @Holf is there a way also to add the file type or extension or its just as simple as spceficy it as filename?
  • littledynamo
    littledynamo almost 8 years
    This is a great workaround for Safari. Use Modernizr to detect when the download attribute is not supported and update the link text!
  • phn
    phn over 7 years
    The problem with this solution is that the file will be downloaded if the user clicks on the link. What if you just want to specify the filename if the user does right-click + Save Link As...?
  • barbariania
    barbariania over 7 years
    there is a bit better way, cuz via this you can't save divided into paragraphs text file. my variant is: var file = new File(rows, "file.csv", {type: 'text/csv'}); var link = document.createElement('a'); link.href = URL.createObjectURL(file); link.download = file.name; link.click(); i've found the answer here
  • fregante
    fregante over 7 years
    For a more complete solution, I suggest using downloadjs on npm
  • deFreitas
    deFreitas over 7 years
    If the file is so long the download fails
  • Admin
    Admin over 7 years
    It works for me but the browser page refreshes after that. Wonder how to prevent that?
  • Pranav Singh
    Pranav Singh about 7 years
    Doesn't work in chrome for file size > 2MB due restriction by chrome stackoverflow.com/questions/695151/…
  • fregante
    fregante about 7 years
    The limit belongs to the data: URI, which is what the question mentions. This answer also works with Blobs and whatever else has a URI
  • Loïc Faure-Lacroix
    Loïc Faure-Lacroix about 7 years
    @LightnessRacesinOrbit Saving an empty file with the URI as the filename would make more sense right? Btw, We have URL.createObjectURL to make things even worse.
  • Lightness Races in Orbit
    Lightness Races in Orbit about 7 years
    @LoïcFaure-Lacroix: If you need a filename, yeah. Otherwise best to save the HTTP request.
  • Aarmora
    Aarmora almost 7 years
    Worked like a charm. Nailed it.
  • FluorescentGreen5
    FluorescentGreen5 almost 7 years
    How is this not the one of the top answers?
  • 3ocene
    3ocene almost 7 years
    If anyone is wondering about support, here's the caniuse page for this feature
  • Jonathan Taylor
    Jonathan Taylor almost 7 years
    this answer is garbage
  • kevinmicke
    kevinmicke over 5 years
    Unfortunately this is the same 2 MB limit in Chrome when used with a data URL: stackoverflow.com/a/41755526/1024735
  • Seph Reed
    Seph Reed over 3 years
    @streetlight 8 years later, and chrome has blocked all top-frame data urls for security reasons. Such is the cycle of tech companies.
  • LF00
    LF00 about 2 years
    I try to use the download for the blob data. But it not works. How to set the download file extension for blob data