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.
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.
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.
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)
}
}
jsfiddle example
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);
}
}
This is my solution. From my point of view, you can not bypass the <a>.
function export2json() {
const data = {
a: '111',
b: '222',
c: '333'
};
const a = document.createElement("a");
a.href = URL.createObjectURL(
new Blob([JSON.stringify(data, null, 2)], {
type: "application/json"
})
);
a.setAttribute("download", "data.json");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
<button onclick="export2json()">Export data to json file</button>
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);
}
}
Working example of a download button, to save a cat photo from an url as "cat.jpg":
HTML:
<button onclick="downloadUrl('https://i.imgur.com/AD3MbBi.jpg', 'cat.jpg')">Download</button>
JavaScript:
function downloadUrl(url, filename) {
let xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = function(e) {
if (this.status == 200) {
const blob = this.response;
const a = document.createElement("a");
document.body.appendChild(a);
const blobUrl = window.URL.createObjectURL(blob);
a.href = blobUrl;
a.download = filename;
a.click();
setTimeout(() => {
window.URL.revokeObjectURL(blobUrl);
document.body.removeChild(a);
}, 0);
}
};
xhr.send();
}
window.location.assign did not work for me. it downloads fine but downloads without an extension for a CSV file on Windows platform. The following worked for me.
var blob = new Blob([csvString], { type: 'text/csv' });
//window.location.assign(window.URL.createObjectURL(blob));
var link = window.document.createElement('a');
link.href = window.URL.createObjectURL(blob);
// Construct filename dynamically and set to link.download
link.download = link.href.split('/').pop() + '.' + extension;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this is a good easy solution for it.
function downloadBloob(blob,FileName) {
var link = document.createElement("a"); // Or maybe get it from the current document
link.href = blob;
link.download = FileName;
link.click();
}
I have this code that correctly works on most of browsers except IE:
<a href="http://xxx.xxx.xxx.xxx/presets/current" download="configuration.bin">
Save
</a>
the problem is that download parameter doesn't work on IE.
To correct it I've tried this code
var request = new XMLHttpRequest();
request.open('GET', "http://xxx.xxx.xxx.xxx/presets/current", true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
var blob = new Blob( [e.target.result] );
navigator.msSaveBlob( blob, 'configuration.bin' );
};
};
request.send();
On AngularJS I've also tried using $http like this code:
$http({method: 'GET', url: "http://xxx.xxx.xxx.xxx/presets/current"})
.success(function(data, status, headers, config) {
var blob = new Blob([data]);
navigator.msSaveBlob( blob, 'configuration.bin' );
})
The problem is that the file size downloaded on Chrome is 134K and the file downloaded on IE with this code is 180K
Question: How could I save file exactly as I get it?
In IE, you can only use msSaveBlob to download files and you need to set the blob type correctly according to your demand. The cross-browser method should be like this:
//change to the type you need
var blob = new Blob([byteArray], { type: 'application/pdf' });
//output file name
var fileName = "test.pdf";
//detect whether the browser is IE/Edge or another browser
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
//To IE or Edge browser, using msSaveorOpenBlob method to download file.
window.navigator.msSaveBlob(blob, fileName);
} else {
//To another browser, create a tag to downlad file.
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}
I use this method to download file and the size is the same in IE and Chrome. You could also refer to these similar threads: link1, link2.
I used jQuery fileDownload plugin to download a file from URL.
$.fileDownload(url,{
contentType: "text/csv",
contentDisposition: 'attachment; filename=' +
url.split("/").pop()
})
.done(function(){console.log('successfully downladed')})
.fail(function(){ console.log(`request failed`)});
I even tried with JavaScript but it's not working
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
fileName = url.split("/").pop();
a.download = fileName
a.click();
window.URL.revokeObjectURL(url);
a.remove();
Your JavaScript does not work probably because you append a to body before you add href and download attributes.
Append just before triggering click
Also remember that this will only work on files with the same-origin URLs (Source).
This attribute only works for same-origin URLs.
var a = document.createElement("a");
a.href = url;
fileName = url.split("/").pop();
a.download = fileName;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
a.remove();
This code snippet will download from external source
<a onclick="saveFile('url')">Download</a>
<script>
function saveFile(url) {
// Get file name from url.
var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function() {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
a.download = filename; // Set the file name.
a.style.display = 'none';
document.body.appendChild(a);
a.click();
delete a;
};
xhr.open('GET', url);
xhr.send();
}
</script>
the saveFile('url') takes string url as an argument so pass in the correct url and your file will download directly. Worked for me
In my application I am receiving a large file from sever (in post response) and I want to download it at client side using javascript. I fount out there is a download attribute that works with chrome and there is a msSaveBlob function that works with IE. But none of them works with Safari. how can I fix the safari? below is my code:
$scope.saveAs = function (data, filename, type) {
if (angular.isUndefined(type)) {
type = 'application/vnd.ms-excel';
}
var blob = new Blob([data], {'type': type});
if (angular.isDefined(window.navigator.msSaveBlob)) {
// IE workaround for HTML7007
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement('a');
// safari doesn't support this yet
if (angular.isUndefined(a.download)) {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
URL.revokeObjectURL(downloadUrl);
}, 100); // cleanup
}
};
I have a code which worked in Chrome and Firefox but not work in IE. It downloads a file stored in a mysql db as a blob record by a link.
Could anyone propose a solution that also works in IE?
The code:
function download(filename, data) {
var a = document.createElement("a");
var blob = b64toBlob(data, "application/octet-stream");
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
document.getElementById('a').click();
window.URL.revokeObjectURL(url);
}
In IE 8 and 9, data URIs can only be used for images, but not for navigation or JavaScript generated file downloads:
function download(filename, data) {
var a = document.createElement("a");
var blob = b64toBlob(data, "application/octet-stream");
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
navigator.msSaveBlob(blob, filename);
//document.getElementById('a').onclick();
window.URL.revokeObjectURL(url);
}