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

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?

This question is related to javascript html url data-uri save-as

The answer is


Using service workers, this is finally possible in the truest sense.

  1. Create a fake URL. For example /saveAs/myPrettyName.jpg
  2. Use URL in <a href, <img src, window.open( url ), absolutely anything that can be done with a "real" URL.
  3. Inside the worker, catch the fetch event, and respond with the correct data.

The browser will now suggest myPrettyName.jpg even if the user opens the file in a new tab, and tries to save it there. It will be exactly as if the file had come from the server.

// In the service worker
self.addEventListener( 'fetch', function(e)
{
    if( e.request.url.startsWith( '/blobUri/' ) )
    {
        // Logic to select correct dataUri, and return it as a Response
        e.respondWith( dataURLAsRequest );
    }
});

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


var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var sessionId ='\n';
var token = '\n';
var caseId = CaseIDNumber + '\n';
var url = casewebUrl+'\n';
var uri = sessionId + token + caseId + url;//data in file
var fileName = "file.i4cvf";// any file name with any extension
if (isIE)
    {
            var fileData = ['\ufeff' + uri];
            var blobObject = new Blob(fileData);
            window.navigator.msSaveOrOpenBlob(blobObject, fileName);
    }
    else //chrome
    {
        window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
         window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) {
            fs.root.getFile(fileName, { create: true }, function (fileEntry) { 
                fileEntry.createWriter(function (fileWriter) {
                    var fileData = ['\ufeff' + uri];
                    var blob = new Blob(fileData);
                    fileWriter.addEventListener("writeend", function () {
                        var fileUrl = fileEntry.toURL();
                        var link = document.createElement('a');
                        link.href = fileUrl;
                        link.download = fileName;
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                    }, false);
                    fileWriter.write(blob);
                }, function () { });
            }, function () { });
         }, function () { });
    }

HTML only: use the download attribute:

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


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

_x000D_
_x000D_
function saveAs(uri, filename) {_x000D_
  var link = document.createElement('a');_x000D_
  if (typeof link.download === 'string') {_x000D_
    link.href = uri;_x000D_
    link.download = filename;_x000D_
_x000D_
    //Firefox requires the link to be in the body_x000D_
    document.body.appendChild(link);_x000D_
    _x000D_
    //simulate click_x000D_
    link.click();_x000D_
_x000D_
    //remove the link when done_x000D_
    document.body.removeChild(link);_x000D_
  } else {_x000D_
    window.open(uri);_x000D_
  }_x000D_
}_x000D_
_x000D_
var file = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'_x000D_
saveAs(file, 'logo.gif');
_x000D_
_x000D_
_x000D_

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, …


Look at this link: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html

Quote:

It even works (as in, doesn't cause a problem) with ;base64 at the end
like this (in Opera at least):

data:text/plain;charset=utf-8;headers=Content-Disposition%3A%20attachment%3B%20filename%3D%22with%20spaces.txt%22%0D%0AContent-Language%3A%20en;base64,4oiaDQo%3D

Also there is some info in the rest messages of the discussion.


<a href=.. download=.. > works for left-click and right-click -> save link as..,

but <img src=.. download=.. > doesn't work for right-click -> save image as.. , "Download.jped" is suggested.

If you combine both:<a href=.. download=..><img src=..></a>

it works for left-click, right-click -> save link as.., right-click -> save image as..

You have to write the data-uri twice (href and src), so for large image files it is better to copy the uri with javascript.

tested with Chrome/Edge 88


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.


Here is a jQuery version based off of Holf's version and works with Chrome and Firefox whereas his version seems to only work with Chrome. It's a little strange to add something to the body to do this but if someone has a better option I'm all for it.

var exportFileName = "export-" + filename;
$('<a></a>', {
    "download": exportFileName,
    "href": "data:," + JSON.stringify(exportData, null,5),
    "id": "exportDataID"
}).appendTo("body")[0].click().remove();

you can add a download attribute to the anchor element.

sample:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>

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

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


You actually can achieve this, in Chrome and FireFox.

Try the following url, it will download the code that was used.

data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==

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

Here is a jQuery version based off of Holf's version and works with Chrome and Firefox whereas his version seems to only work with Chrome. It's a little strange to add something to the body to do this but if someone has a better option I'm all for it.

var exportFileName = "export-" + filename;
$('<a></a>', {
    "download": exportFileName,
    "href": "data:," + JSON.stringify(exportData, null,5),
    "id": "exportDataID"
}).appendTo("body")[0].click().remove();

No.

The entire purpose is that it's a datastream, not a file. The data source should not have any knowledge of the user agent handling it as a file... and it doesn't.


It's kind of hackish, but I've been in the same situation before. I was dynamically generating a text file in javascript and wanted to provide it for download by encoding it with the data-URI.

This is possible with minormajor user intervention. Generate a link <a href="data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>. As I said, this is inelegant, but it works if you do not need a professional solution.

This could be made less painful by using flash to copy the name into the clipboard first. Of course if you let yourself use Flash or Java (now with less and less browser support I think?), you could probably find a another way to do this.


You actually can achieve this, in Chrome and FireFox.

Try the following url, it will download the code that was used.

data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==

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.


The following Javascript snippet works in Chrome by using the new 'download' attribute of links and simulating a click.

function downloadWithName(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  link.click();
}

And the following example shows it's use:

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")

It's kind of hackish, but I've been in the same situation before. I was dynamically generating a text file in javascript and wanted to provide it for download by encoding it with the data-URI.

This is possible with minormajor user intervention. Generate a link <a href="data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>. As I said, this is inelegant, but it works if you do not need a professional solution.

This could be made less painful by using flash to copy the name into the clipboard first. Of course if you let yourself use Flash or Java (now with less and less browser support I think?), you could probably find a another way to do this.


HTML only: use the download attribute:

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


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

_x000D_
_x000D_
function saveAs(uri, filename) {_x000D_
  var link = document.createElement('a');_x000D_
  if (typeof link.download === 'string') {_x000D_
    link.href = uri;_x000D_
    link.download = filename;_x000D_
_x000D_
    //Firefox requires the link to be in the body_x000D_
    document.body.appendChild(link);_x000D_
    _x000D_
    //simulate click_x000D_
    link.click();_x000D_
_x000D_
    //remove the link when done_x000D_
    document.body.removeChild(link);_x000D_
  } else {_x000D_
    window.open(uri);_x000D_
  }_x000D_
}_x000D_
_x000D_
var file = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'_x000D_
saveAs(file, 'logo.gif');
_x000D_
_x000D_
_x000D_

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, …


This one works with Firefox 43.0 (older not tested):

dl.js:

function download() {
  var msg="Hello world!";
  var blob = new File([msg], "hello.bin", {"type": "application/octet-stream"});

  var a = document.createElement("a");
  a.href = URL.createObjectURL(blob);

  window.location.href=a;
}

dl.html

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8"/>
    <title>Test</title>
    <script type="text/javascript" src="dl.js"></script>
</head>

<body>
<button id="create" type="button" onclick="download();">Download</button>
</body>
</html>

If button is clicked it offered a file named hello.bin for download. Trick is to use File instead of Blob.

reference: https://developer.mozilla.org/de/docs/Web/API/File


No.

The entire purpose is that it's a datastream, not a file. The data source should not have any knowledge of the user agent handling it as a file... and it doesn't.


There is a tiny workaround script on Google Code that worked for me:

http://code.google.com/p/download-data-uri/

It adds a form with the data in it, submits it and then removes the form again. Hacky, but it did the job for me. Requires jQuery.

This thread showed up in Google before the Google Code page and I thought it might be helpful to have the link in here, too.


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)


var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var sessionId ='\n';
var token = '\n';
var caseId = CaseIDNumber + '\n';
var url = casewebUrl+'\n';
var uri = sessionId + token + caseId + url;//data in file
var fileName = "file.i4cvf";// any file name with any extension
if (isIE)
    {
            var fileData = ['\ufeff' + uri];
            var blobObject = new Blob(fileData);
            window.navigator.msSaveOrOpenBlob(blobObject, fileName);
    }
    else //chrome
    {
        window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
         window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) {
            fs.root.getFile(fileName, { create: true }, function (fileEntry) { 
                fileEntry.createWriter(function (fileWriter) {
                    var fileData = ['\ufeff' + uri];
                    var blob = new Blob(fileData);
                    fileWriter.addEventListener("writeend", function () {
                        var fileUrl = fileEntry.toURL();
                        var link = document.createElement('a');
                        link.href = fileUrl;
                        link.download = fileName;
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                    }, false);
                    fileWriter.write(blob);
                }, function () { });
            }, function () { });
         }, function () { });
    }

Look at this link: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html

Quote:

It even works (as in, doesn't cause a problem) with ;base64 at the end
like this (in Opera at least):

data:text/plain;charset=utf-8;headers=Content-Disposition%3A%20attachment%3B%20filename%3D%22with%20spaces.txt%22%0D%0AContent-Language%3A%20en;base64,4oiaDQo%3D

Also there is some info in the rest messages of the discussion.


Using service workers, this is finally possible in the truest sense.

  1. Create a fake URL. For example /saveAs/myPrettyName.jpg
  2. Use URL in <a href, <img src, window.open( url ), absolutely anything that can be done with a "real" URL.
  3. Inside the worker, catch the fetch event, and respond with the correct data.

The browser will now suggest myPrettyName.jpg even if the user opens the file in a new tab, and tries to save it there. It will be exactly as if the file had come from the server.

// In the service worker
self.addEventListener( 'fetch', function(e)
{
    if( e.request.url.startsWith( '/blobUri/' ) )
    {
        // Logic to select correct dataUri, and return it as a Response
        e.respondWith( dataURLAsRequest );
    }
});

This one works with Firefox 43.0 (older not tested):

dl.js:

function download() {
  var msg="Hello world!";
  var blob = new File([msg], "hello.bin", {"type": "application/octet-stream"});

  var a = document.createElement("a");
  a.href = URL.createObjectURL(blob);

  window.location.href=a;
}

dl.html

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8"/>
    <title>Test</title>
    <script type="text/javascript" src="dl.js"></script>
</head>

<body>
<button id="create" type="button" onclick="download();">Download</button>
</body>
</html>

If button is clicked it offered a file named hello.bin for download. Trick is to use File instead of Blob.

reference: https://developer.mozilla.org/de/docs/Web/API/File


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)


The following Javascript snippet works in Chrome by using the new 'download' attribute of links and simulating a click.

function downloadWithName(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  link.click();
}

And the following example shows it's use:

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")

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)


<a href=.. download=.. > works for left-click and right-click -> save link as..,

but <img src=.. download=.. > doesn't work for right-click -> save image as.. , "Download.jped" is suggested.

If you combine both:<a href=.. download=..><img src=..></a>

it works for left-click, right-click -> save link as.., right-click -> save image as..

You have to write the data-uri twice (href and src), so for large image files it is better to copy the uri with javascript.

tested with Chrome/Edge 88


you can add a download attribute to the anchor element.

sample:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>

There is a tiny workaround script on Google Code that worked for me:

http://code.google.com/p/download-data-uri/

It adds a form with the data in it, submits it and then removes the form again. Hacky, but it did the job for me. Requires jQuery.

This thread showed up in Google before the Google Code page and I thought it might be helpful to have the link in here, too.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to url

What is the difference between URL parameters and query strings? Allow Access-Control-Allow-Origin header using HTML5 fetch API File URL "Not allowed to load local resource" in the Internet Browser Slack URL to open a channel from browser Getting absolute URLs using ASP.NET Core How do I load an HTTP URL with App Transport Security enabled in iOS 9? Adding form action in html in laravel React-router urls don't work when refreshing or writing manually URL for public Amazon S3 bucket How can I append a query parameter to an existing URL?

Examples related to data-uri

Send a base64 image in HTML email Drawing an image from a data URL to a canvas Download data url file Is embedding background image data into CSS as Base64 good or bad practice? Is there any way to specify a suggested filename when using data: URI?

Examples related to save-as

How to save as a new file and keep working on the original one in Vim? Is there any way to specify a suggested filename when using data: URI?