This code works in all major browsers excpet in latest Opera 71 (Windows).
The behaviour is that no error or info shows up but the download never starts from end user perspective. In developer tools I see the binary content of the example pdf document in response tab.
It seems that the dynamic creation of tags is not working.
function downloadFile(urlToSend) {
var req = new XMLHttpRequest();
req.open("GET", urlToSend, true);
req.responseType = "blob";
req.onload = function (event) {
var URL = window.URL || window.webkitURL;
var contentType = req.getResponseHeader('content-type');
var blob = new Blob([req.response], {type: contentType});
var downloadUrl = URL.createObjectURL(blob);
var contentDisposition = req.getResponseHeader('content-disposition');
//var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
var filename = 'doku.pdf'; //contentDisposition.match(/filename*="(.+)"/)[1];
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
//code which gets executed by Opera
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
};
req.send();
}
Related
I have a PHP file that returns output in PDF - Works fine if I access the file directly.
I'd like to retrieve the PDF file through AJAX.
In native Javascript, it works fine:
var req = new XMLHttpRequest();
req.open("POST", "./api/pdftest.php?wpid="+wpid, true);
req.responseType = "blob";
req.onreadystatechange = function ()
{
if (req.readyState === 4 && req.status === 200)
{
var blob=req.response;
var filename = "test.pdf";
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "test.pdf";
link.click();
var file = new File([blob], filename, { type: 'application/force-download' });
window.open(URL.createObjectURL(file));
}
};
req.send();
But I guess I'd use jQuery to ensure cross browser compatibility (although the snippet above works in Edge, Chrome and Firefox on pc, I haven't tested it in other browsers/on other platforms)
So I tried to rewrite the function:
url='./api/pdftest.php?wpid='+wpid;
$.ajax(
{
url: url,
method: 'POST',
responseType: 'blob',
success: function(data)
{
var filename='test.pdf';
var blob=new Blob([data]);
var filename = "test.pdf";
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "test.pdf";
link.click();
var file = new File([blob], filename, { type: 'application/force-download' });
window.open(URL.createObjectURL(file));
}
});
The jQuery equivalent allows me to download a PDF file but … the PDF file is empty.
So I guess I am doing something wrong, probably in the DATA to BLOB conversion. But what? I hope somebody can see what I am doing wrong.
I've been using ages on StackOverflow, read many suggestions - but didn't find any answer. I simply can't see the forest for the trees.
Looking at the documentation for the jQuery.ajax() function, we see there's no setting called responseType, so you need to use xhrFields to directly set a property of the XHR object. And, since you're only setting the URL and success callback, we can just use the shorter jquery.post() function.
So the data is returned, we make a Blob and then a URL to download it. I'm not on Windows so I can't test if that link I constructed will work as expected, but figured I'd do it the jQuery way.
var url = './api/pdftest.php?wpid=' + wpid;
$.post({
url: url,
xhrFields: {responseType: "blob"},
success: function(data) {
// don't set the MIME type to pdf or it will display
var blob = new Blob([data], {type: "application/octet-stream"});
// build a blob URL
var bloburl = window.URL.createObjectURL(blob);
// trigger download for edge
var link = $("<a>").attr({href: bloburl, download: "test.pdf"}).click();
// trigger download for other browsers
window.open(bloburl);
}
});
Probably double!
This is the solution I found thanks to Hisham at Download pdf file using jquery ajax:
First, add the following plugin that can be used to the XHR V2 capabilities missing in JQuery: https://github.com/acigna/jquery-ajax-native
Then:
url='./api/pdftest.php?wpid='+wpid;
$.ajax(
{
dataType: 'native',
url: url,
xhrFields:
{
responseType: 'blob'
},
success: function(blob)
{
var filename = "test.pdf";
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "test.pdf";
link.click();
var file = new File([blob], filename, { type: 'application/force-download' });
window.open(URL.createObjectURL(file));
}
});
This seems to be working.
Note: the window.open() is to make download possible in Firefox, the link.click() method Works in Edge, Chrome and Opera
Thanks to miken32 for pointing into the right direction.
As binary data is not possible to retrieve through jQuery.ajax, Native is the only way, at least for now. The following method works in Edge, Firefox, Chrome and Opera - tested on WIndows 10.
var req = new XMLHttpRequest();
req.open("POST", "./api/pdftest.php?wpid="+wpid, true);
req.responseType = "blob";
req.onreadystatechange = function ()
{
if (req.readyState === 4 && req.status === 200)
{
var blob=req.response;
var filename = "test.pdf";
var link = document.createElement('a');
link.setAttribute("type", "hidden"); // make it hidden if needed
link.href = window.URL.createObjectURL(blob);
link.download = "test.pdf";
document.body.appendChild(link);
link.click();
link.remove();
var file = new File([blob], filename, { type: 'application/force-download' });
//window.open(URL.createObjectURL(file));
}
};
req.send();
Hi I am new to java script, I am trying to download zip file from a web server running in http://10.1.2.137:5000/download.
When I access the URL alone in the browser as http://10.1.2.137:5000/download, te zip file is getting downloaded , but when I call from java script , the zip file is getting corrupted it seems. Not able to open the zip file with win rar.
Not sure this is the issue with CORS.
$scope.downloadData = function (){
console.log ('Entering in to Download Method')
var url = 'http://10.1.2.137:5000/download';
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.responseType = "arraybuffer";
var linkElement = document.createElement('iframe');
document.body.appendChild(linkElement)
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var blob = new Blob([str2bytes(xhr.response)], {type: "application/zip"});
var fileName = "logs.zip";
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display:none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}
}
}
};
You can use window.open, this will instruct the browser to open the url and start download. e.g.
window.open("http://10.1.2.137:5000/download","_self");
Is it possible to use an ajax call to open FileStreamResult as a downloaded file?
Controller method
public FileStreamResult DownloadPDF()
{
var stream = myHandler.getFileStream("myfile.pdf");
return File(stream, "application/pdf", "myfile.pdf"));
}
Html code
Click Me
<script type="text/javascript>
$("a.mydownload").click(function () {
$.ajax({
method: 'GET',
url: 'http://myserver/file/DownloadPDF',
success: function (data, status, jqXHR) {
var blob = new Blob([data], { type: "application/pdf" })
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.click();
}
});
});
</script>
Running on IE I get access denied, but on Chrome it runs fine. I do however get a "blank"/invalid pdf.
Use XMLHttpRequest() with responseType set to "blob", add download attribute to <a> element
$("a.mydownload").click(function () {
var request = new XMLHttpRequest();
request.responseType = "blob";
request.open("GET", "http://myserver/file/DownloadPDF");
request.onload = function() {
var url = window.URL.createObjectURL(this.response);
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.download = this.response.name || "download-" + $.now()
a.click();
}
request.send();
});
alternatively, you can use jquery-ajax-blob-arraybuffer.js. See also Add support for HTML5 XHR v2 with responseType set to 'arraybuffer' on $.ajax
Still had issues with IE11, but a minor change to #guest271314 solutions, seems to do the trick.
Set responseType after open.
Use msSaveBlob on IE
$("a.mydownload").click(function() {
var request = new XMLHttpRequest();
request.open("GET", "http://myserver/file/DownloadPDF");
request.responseType = "blob";
request.onload = function() {
var msie = window.navigator.userAgent.indexOf("MSIE");
if (msie > 0) {
window.navigator.msSaveBlob(this.response, "myfile.pdf");
} else {
var url = window.URL.createObjectURL(this.response);
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.download = this.response.name || "download-" + $.now()
a.click();
}
}
request.send();
});
I have converted my existing data to text/csv and able to download the file in Chrome but when tried with Safari on iPad or Mac it opens a tab with name "unknown"/ "Untitled" . This is the code I am using -
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv,'+ encodeURI(response);
hiddenElement.target = '_blank';
hiddenElement.download = 'purchase.csv';
hiddenElement.click();
Is there anyway I can able to show the downloaded file as "purchase.csv" for safari.
Try this one
var a = document.createElement('a');
a.setAttribute("href",URL);
a.setAttribute("target", "_blank");
var dispatch = document.createEvent("HTMLEvents");
dispatch.initEvent("click", true, true);
a.dispatchEvent(dispatch);
return false;
IF the data is LOCAL -- Easy!
We just use window.URL.createObjectURL(). Let's set some globals...
//var response = Already defined by OP! Not sure what it is, but it's data to save.
var mimetype = "text/csv";
var filename = "purchase.csv";
Now we just set the header by means of the type argument to window.URL.createObjectURL()...
a.href = window.URL.createObjectURL(new Blob([response], {
encoding: "UTF-8",
type: mimetype + ";charset=UTF-8",
}));
IF the data is on the WEB -- Still easy, just more effort!
We can do this by means of XMLHTTPRequest() to download the file data, window.URL.createObjectURL() to cast the data to a blob type with MIME type headers, and then proceed normally in setting a.download = filename; and a.click();.
An abstract function for download file data directly to the JavaScript environment...
function load(url, callback) {
var xhr = new XMLHTTPRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) callback(xhr.responseText);
};
xhr.open("GET", url, true);
}
Then download the data, build the link, and click it:
load("site.com/t.txt", function (contents) {
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([response], {
encoding: "UTF-8",
type: mimetype + ";charset=UTF-8",
}));
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
});
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();
}