JavaScript blob filename without link
Solution 1
The only way I'm aware of is the trick used by FileSaver.js:
- Create a hidden
<a>
tag. - Set its
href
attribute to the blob's URL. - Set its
download
attribute to the filename. - Click on the
<a>
tag.
Here is a simplified example (jsfiddle):
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, fileName) {
var json = JSON.stringify(data),
blob = new Blob([json], {type: "octet/stream"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
var data = { x: 42, s: "hello, world", d: new Date() },
fileName = "my-download.json";
saveData(data, fileName);
I wrote this example just to illustrate the idea, in production code use FileSaver.js instead.
Notes
- Older browsers don't support the "download" attribute, since it's part of HTML5.
- Some file formats are considered insecure by the browser and the download fails. Saving JSON files with txt extension works for me.
Solution 2
I just wanted to expand on the accepted answer with support for Internet Explorer (most modern versions, anyways), and to tidy up the code using jQuery:
$(document).ready(function() {
saveFile("Example.txt", "data:attachment/text", "Hello, world.");
});
function saveFile (name, type, data) {
if (data !== null && navigator.msSaveBlob)
return navigator.msSaveBlob(new Blob([data], { type: type }), name);
var a = $("<a style='display: none;'/>");
var url = window.URL.createObjectURL(new Blob([data], {type: type}));
a.attr("href", url);
a.attr("download", name);
$("body").append(a);
a[0].click();
window.URL.revokeObjectURL(url);
a.remove();
}
Here is an example Fiddle. Godspeed.
Solution 3
Same principle as the solutions above. But I had issues with Firefox 52.0 (32 bit) where large files (>40 MBytes) are truncated at random positions. Re-scheduling the call of revokeObjectUrl() fixes this issue.
function saveFile(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
const a = document.createElement('a');
document.body.appendChild(a);
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
setTimeout(() => {
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 0)
}
}
Solution 4
Late, but since I had the same problem I add my solution:
function newFile(data, fileName) {
var json = JSON.stringify(data);
//IE11 support
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
let blob = new Blob([json], {type: "application/json"});
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {// other browsers
let file = new File([json], fileName, {type: "application/json"});
let exportUrl = URL.createObjectURL(file);
window.location.assign(exportUrl);
URL.revokeObjectURL(exportUrl);
}
}
Solution 5
saveFileOnUserDevice = function(file){ // content: blob, name: string
if(navigator.msSaveBlob){ // For ie and Edge
return navigator.msSaveBlob(file.content, file.name);
}
else{
let link = document.createElement('a');
link.href = window.URL.createObjectURL(file.content);
link.download = file.name;
document.body.appendChild(link);
link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));
link.remove();
window.URL.revokeObjectURL(link.href);
}
}
Related videos on Youtube
Ash Blue
Ash has been leading front-end teams for 10+ years in creating award winning websites. Working with agencies, financial, and entertainment. His full stack experience helps him empower teams to create scalable front-end solutions that harmonize communication with the back-end. In addition to mentoring, open source contributions, and organizing development Meetup events. Ash co-authored HTML5 in Action under Manning Publications, writing on interactive media APIs.
Updated on January 06, 2022Comments
-
Ash Blue over 2 years
How do you set the name of a blob file in JavaScript when force downloading it through
window.location
?function newFile(data) { var json = JSON.stringify(data); var blob = new Blob([json], {type: "octet/stream"}); var url = window.URL.createObjectURL(blob); window.location.assign(url); }
Running the above code downloads a file instantly without a page refresh that looks like:
bfefe410-8d9c-4883-86c5-d76c50a24a1d
I want to set the filename as my-download.json instead.
-
Ash Blue over 10 yearsOddly it seems to be failing when I copy and paste this into CodePen. Although your code seems legit and good codepen.io/ashblue/pen/jEhmH
-
kol over 10 yearsYour codepen code works for me in Chrome. The json file is saved into the download folder of Chrome.
-
kol over 10 years@AshBlue The "download" attribute needs HTML5. My code is just an example, you could also try the FileSaver.js demo page: eligrey.com/demos/FileSaver.js
-
Ash Blue over 10 yearsI'm getting "Failed - No file" on Chrome Windows ver 30. Is it maybe a Windows exclusive bug?
-
kol over 10 yearsThe download works for me on a Windows 7 PC, but I got the "Failed - No file" message on Windows XP. Interestingly, The FileSaver.js demo page is able to download files to XP.
-
kol over 10 yearsI've found a workaround: if I change the extension to txt, then the download works.
-
kol over 10 yearsInterestingly, if you repeatedly try to download a txt this way (by pressing the Run button on jsfiddle.net again and again), the download sometimes fails.
-
philx_x about 9 yearsi allready have an <a id="saveToJson">save as JSON</a> link. i do the Blob creatin logic in the $("#saveToJson") callback function but the problem is i can't do this.click() unless the function is gonna run itself over and over again. ps: i don't like to create those hidden workaround filds so i wanted to set the attributes of my element when it's clicked.
-
kol about 9 years@philx_x Since you already have an <a> tag, and create the Blob in its click handler, you don't have to call
.click()
yourself, because it will cause infinite recursion. -
kol over 8 years@xheyhenry FileSaver.js should work in IE10+: github.com/eligrey/FileSaver.js/#supported-browsers There is a workaround for IE<10: github.com/eligrey/FileSaver.js/#ie--10
-
manojadams over 6 yearsJust wanted to mention that this solution will not work for files with sizes greater than a particular threshold. e.g-> 2 MB for chrome. This size varies from browser to browser.
-
Adrián Paredes over 6 yearsThis does not work for me because I need to open the file in a new tab. I have to show a PDF in Chrome, but I need to show a user friendly name in the URL toolbar, and if the user wants to download through the download icon, I have to put the same user friendly name in the file.
-
Rafael Andrade almost 6 yearsCan I do this kind of thing without using <a> tag and window. Window is not available in all browsers and I do not want to create an <a> tag in my angular app.
-
Ixio over 5 yearsstackoverflow.com/a/52273870/2730032 works for me without needing the <a> trick used here and in the other answers. Is there a reason why it's not more upvoted and that this is still the top answer ?
-
kol over 5 years@Ixio Isn't
msSaveOrOpenBlob
Internet Explorer specific? -
Ixio over 5 years@kol probably but I used the technique for other browsers: window.location = URL.createObjectURL(new File(...)) and it works fine for me on Firefox (I don't know about other browsers).
-
Konrad Höffner over 5 yearsFor some reason, this fails for me when using Babel with Webpack, because the body element is not available yet, even if the code is only called after the document is loaded or not called at all. When using the untranspiled ES6 module source code, it works fine. I changed it to a normal function and declaring a reused a element outside of the function.
-
Russell Phillips over 5 yearsI found that this setTimeout() hack fixes MS Edge, where the file would not download at all. However, only the call to revokeObjectURL() needs to be delayed.
-
Enrique Altuna over 5 yearsis there any way to open in it a new window?
-
Ram Babu over 5 yearsThanks @ben. This is working fine. No dom elements, nothing like to trigger like click event. It just works awesome with proper extension. But the given file name is not considered, downloading "<object_url_id>.csv" instead of "<myfileName>.csv"
-
Fred over 5 yearsCalling
revokeObjectURL
afterlocation.assign
works fine in Firefox, but breaks the download on Chrome. -
Fred over 5 yearsI think you can call
link.click()
instead of dispatching a mouse event. -
Jacques Olivier over 5 yearsI found that the "if (window.navigator.msSaveOrOpenBlob)" is what did the trick for me
-
N8allan almost 5 yearsWorked perfectly.
-
beyond-code almost 5 yearsJust to add, you don't need to actually mount the a tag to the body in order for this to work (tried just now in Chrome)
-
user1477388 over 4 yearsNote that "Edge does not support the File constructor." Ref. caniuse.com/#feat=fileapi
-
elahehab over 4 yearsI used the accepted solution but it didn't work at firefox! I still don't know why. Your solution worked in firefox. Thanks.
-
Luiz Felipe about 4 yearsThis should be the correct answer. No point in creating useless objects in the DOM tree
-
Luiz Felipe about 4 yearsNow it does, since Jan '20
-
Manu Artero about 4 yearsAs @RamBabuS says, this is not keeping
fileName
, but besides that works perfectly for me -
junvar about 4 yearsThere is no need to call revokeObjectURL, the URL will automatically be revoked when the creating document (the page you were on) is closed. Which is also why you must use a new tab to view the file (at least in chrome).
-
F. Vosnim almost 4 yearsCan I download a blob video with this function?
-
Gerros over 3 yearsThe filename property works in firefox, but not in chrome... anyone a solution for chrome?
-
Experimenter over 2 yearsThe file name is not working in Chrome, so don't waste your time
-
LF00 about 2 yearsHow can I make works for the video tag with blob data.How to set the download file extension for blob data
-
Andrej Gaspar about 2 yearswell done, thanks for help!
-
user210757 about 2 yearsWhy is saveData declared as an IIFE?
-
phil294 almost 2 yearsweirdly enough, this adds auto file extensions when the filename is without one... I had some logfile called
logfile
and chrome made itlogfile.xml
without any indication from my side (it's not even an xml file)