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 want to download a PDF file when I press an HTML button. I want the click event to be in a JS file.
I need something that do the same thig as the code below but in a JS file :
<a href="url" download>
<button>Download</button>
</a>
I tried to follow this but it doesn't create my button:
var req = new XMLHttpRequest();
req.open("GET", "url", true);
req.responseType = "blob";
req.onreadystatechange = function () {
if (req.readyState === 4 && req.status === 200) {
// test for IE
if (typeof window.navigator.msSaveBlob === 'function') {
window.navigator.msSaveBlob(req.response, "PdfName-" + new Date().getTime() + ".pdf");
} else {
var blob = req.response;
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "PdfName-" + new Date().getTime() + ".pdf";
// append the link to the document body
document.body.appendChild(link);
link.click();
}
}
};
req.send();
If you already have the URL, and you just want the file to be downloaded, use an invisible link, and click it for the user:
function triggerDownload(url, filename) {
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.style.display = `none`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
Note the adding to the document, which is required for the link to count as a real link.
Just made it work, here is my working code
const blob = new Blob([response], { type: 'application/pdf' });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "filename.pdf";
link.click();
I would agree with mike, you don't need any ajax to download it
if you want to add the timestamp for when you downloaded it, just change the download attribute dynamical
Download
or better yet add it in the backend using content-disposition attachment header
The function I created works for Chrome,Firefox and Safari, I am having difficulties as to why it's not working for the iphone. Here is my code:
downloadCSV = function(content, fileName, mimeType) {
var a = document.createElement('a');
mimeType = mimeType || 'application/octet-stream';
if (navigator.msSaveBlob) { // IE10
navigator.msSaveBlob(new Blob([content], {
type: mimeType
}), fileName);
} else if (URL && 'download' in a) { //html5 A[download]
a.href = URL.createObjectURL(new Blob([content], {
type: mimeType
}));
a.setAttribute('download', fileName);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
location.href = 'data:application/octet-stream,' + encodeURIComponent(content); // only this mime type is supported
}
}
On all browsers mentioned it successfully converts into a downloadable csv but for the iphone it becomes a .txt file which has the string for the csv. I was hoping someone here encountered a similar issue and was able to make a solution.
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
}
};