I have a code to export json data to Excel via javascript, it works fine in Chrome. However the same code doesn't work in IE where a click event is fired via code:
download = function (content, filename, contentType) {
if (!contentType) contentType = 'application/octet-stream';
var a = document.getElementById('idA');
var blob = new Blob([content], {
'type': contentType
});
a.href = window.URL.createObjectURL(blob);
a.download = filename;
var eid = '#' + id;
//$(eid)[0].click();
var l = document.getElementById('idL');
alert('1'); //this one works
l.click();
alert('2'); //this doesn't
};
download function is fired by clicking a button and clicking anchor href causes blob downloading in Excel. I need to make this work in IE.
Related
I'd like to have a button on a HTML page, when I click the button, a JavaScript function have to copy the current URL and write to an already existing TXT file, and overwrite it's current data.
I tried this code:
var button = document.getElementById("myButton");
// Attach a click event listener to the button
button.addEventListener("click", function() {
// Wait 0.2 seconds before executing the function
setTimeout(function() {
// Get the current URL
var currentURL = window.location.href;
// Open or create the text file and overwrite its current data
var file = new File([currentURL], "URLs.txt", {type: "text/plain", overwrite: true});
// Copy the contents of the file
file.select();
document.execCommand("copy");
}, 200);
});
Call the following function with the text file content:
function downloadTxtFile(content) {
var aElem = document.createElement("a");
aElem.href = "data:text/plain;charset=utf-8," + encodeURIComponent(content);
aElem.setAttribute("download", "filename.txt");
aElem.style.display = "none";
document.body.appendChild(aElem);
aElem.click();
aElem.remove();
}
downloadTxtFile("https://google.com.br");
You can change the function to get the filename. In this form, it only gets the content of the file, which is the URL.
I want to force the browser to download a pdf file.
I am using the following code :
<a href="../doc/quot.pdf" target=_blank>Click here to Download quotation</a>
It makes the browser open the pdf in a new window, but I want it to download to the hard drive when a user clicks it.
I found that Content-disposition is used for this, but how do I use it in my case?
On the HTTP Response where you are returning the PDF file, ensure the content disposition header looks like:
Content-Disposition: attachment; filename=quot.pdf;
See content-disposition on the wikipedia MIME page.
With recent browsers you can use the HTML5 download attribute as well:
<a download="quot.pdf" href="../doc/quot.pdf">Click here to Download quotation</a>
It is supported by most of the recent browsers except MSIE11. You can use a polyfill, something like this (note that this is for data uri only, but it is a good start):
(function (){
addEvent(window, "load", function (){
if (isInternetExplorer())
polyfillDataUriDownload();
});
function polyfillDataUriDownload(){
var links = document.querySelectorAll('a[download], area[download]');
for (var index = 0, length = links.length; index<length; ++index) {
(function (link){
var dataUri = link.getAttribute("href");
var fileName = link.getAttribute("download");
if (dataUri.slice(0,5) != "data:")
throw new Error("The XHR part is not implemented here.");
addEvent(link, "click", function (event){
cancelEvent(event);
try {
var dataBlob = dataUriToBlob(dataUri);
forceBlobDownload(dataBlob, fileName);
} catch (e) {
alert(e)
}
});
})(links[index]);
}
}
function forceBlobDownload(dataBlob, fileName){
window.navigator.msSaveBlob(dataBlob, fileName);
}
function dataUriToBlob(dataUri) {
if (!(/base64/).test(dataUri))
throw new Error("Supports only base64 encoding.");
var parts = dataUri.split(/[:;,]/),
type = parts[1],
binData = atob(parts.pop()),
mx = binData.length,
uiArr = new Uint8Array(mx);
for(var i = 0; i<mx; ++i)
uiArr[i] = binData.charCodeAt(i);
return new Blob([uiArr], {type: type});
}
function addEvent(subject, type, listener){
if (window.addEventListener)
subject.addEventListener(type, listener, false);
else if (window.attachEvent)
subject.attachEvent("on" + type, listener);
}
function cancelEvent(event){
if (event.preventDefault)
event.preventDefault();
else
event.returnValue = false;
}
function isInternetExplorer(){
return /*#cc_on!#*/false || !!document.documentMode;
}
})();
From the following code I'm creating a dynamic anchor tag which downloads a file. This code works well in Chrome but not in IE. How can I get this working
<div id="divContainer">
<h3>Sample title</h3>
</div>
<button onclick="clicker()">Click me</button>
<script type="text/javascript">
function clicker() {
var anchorTag = document.createElement('a');
anchorTag.href = "http://cdn1.dailymirror.lk/media/images/finance.jpg";
anchorTag.download = "download";
anchorTag.click();
var element = document.getElementById('divContainer');
element.appendChild(anchorTag);
}
</script>
Internet Explorer does not presently support the Download attribute on A tags.
See http://caniuse.com/download and http://status.modern.ie/adownloadattribute; the latter indicates that the feature is "Under consideration" for IE12.
In my case, since there's a requirement to support the usage of IE 11 (version 11.0.9600.18665), I ended up using the solution provided by #Henners on his comment:
// IE10+ : (has Blob, but not a[download] or URL)
if (navigator.msSaveBlob) {
return navigator.msSaveBlob(blob, fileName);
}
It's quite simple and practical.
Apparently, this solution was found on the Javascript download function created by dandavis.
Old question, but thought I'd add our solution. Here is the code I used on my last project. It's not perfect, but it passed QA in all browsers and IE9+.
downloadCSV(data,fileName){
var blob = new Blob([data], {type: "text/plain;charset=utf-8;"});
var anchor = angular.element('<a/>');
if (window.navigator.msSaveBlob) { // IE
window.navigator.msSaveOrOpenBlob(blob, fileName)
} else if (navigator.userAgent.search("Firefox") !== -1) { // Firefox
anchor.css({display: 'none'});
angular.element(document.body).append(anchor);
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURIComponent(data),
target: '_blank',
download: fileName
})[0].click();
anchor.remove();
} else { // Chrome
anchor.attr({
href: URL.createObjectURL(blob),
target: '_blank',
download: fileName
})[0].click();
}
}
Using the ms specific API worked best for us in IE. Also note that some browsers require the anchor to actually be in the DOM for the download attribute to work, whereas Chrome, for example, does not. Also, we found some inconsistencies with how Blobs work in various browsers. Some browsers also have an export limit. This allows the largest possible CSV export in each browser afaik.
As of build 10547+, the Microsoft Edge browser is now supporting the download attribute on a tags.
Download Image
Edge features update: https://dev.windows.com/en-us/microsoft-edge/platform/changelog/desktop/10547/
a[download] standard: http://www.w3.org/html/wg/drafts/html/master/links.html#attr-hyperlink-download
This code fragment allows saving blob in the file in IE, Edge and other modern browsers.
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
// Extract filename form response using regex
var filename = "";
var disposition = request.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
if (window.navigator.msSaveOrOpenBlob) { // for IE and Edge
window.navigator.msSaveBlob(request.response, filename);
} else {
// for modern browsers
var a = document.createElement('a');
a.href = window.URL.createObjectURL(request.response);
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
}
button.disabled = false;
dragArea.removeAttribute('spinner-visible');
// spinner.style.display = "none";
};
request.open("POST", "download");
request.responseType = 'blob';
request.send(formData);
For IE and Edge use: msSaveBlob
Use my function
It bind your atag to download file in IE
function MS_bindDownload(el) {
if(el === undefined){
throw Error('I need element parameter.');
}
if(el.href === ''){
throw Error('The element has no href value.');
}
var filename = el.getAttribute('download');
if (filename === null || filename === ''){
var tmp = el.href.split('/');
filename = tmp[tmp.length-1];
}
el.addEventListener('click', function (evt) {
evt.preventDefault();
var xhr = new XMLHttpRequest();
xhr.onloadstart = function () {
xhr.responseType = 'blob';
};
xhr.onload = function () {
navigator.msSaveOrOpenBlob(xhr.response, filename);
};
xhr.open("GET", el.href, true);
xhr.send();
})
}
Append child first and then click
Or you can use window.location= 'url' ;
As mentioned in earlier answer , download attribute is not supported in IE . As a work around, you can use iFrames to download the file . Here is a sample code snippet.
function downloadFile(url){
var oIframe = window.document.createElement('iframe');
var $body = jQuery(document.body);
var $oIframe = jQuery(oIframe).attr({
src: url,
style: 'display:none'
});
$body.append($oIframe);
}
I copied the code from here and updated it for ES6 and ESLint and added it to my project.
You can save the code to download.js and use it in your project like this:
import Download from './download'
Download('/somefile.png', 'somefile.png')
Note that it supports dataURLs (from canvas objects), and more... see https://github.com/rndme for details.
I have the following server side code in web api
tempResponse = Request.CreateResponse(HttpStatusCode.OK);
tempResponse.Content = new StreamContent(stream);
tempResponse.Content.Headers.Add(#"Content-type", "application/pdf");
tempResponse.Content.Headers.ContentType = new
System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
tempResponse.Content.Headers.ContentDisposition = new
System.Net.Http.Headers.ContentDispositionHeaderValue("inline");
I am using angular JS and following is the code in my javascript file.
$http.post(apiURL + "/DownloadPdf", data, { responseType: 'arraybuffer'}, config)
.then(function (result) {
var file = new Blob([result.data], { type: 'application/pdf' })
var fileName = "CommissionStatement.pdf"
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.location.href = 'Assets/Document CheckList.pdf'
window.navigator.msSaveOrOpenBlob(file, fileName)
} else {
var objectUrl = URL.createObjectURL(file)
window.open(window.location.href = 'Assets/Document CheckList.pdf', '_blank')
window.open(objectUrl, '_blank')
$window.location.href =
window.location.protocol + "//" +
window.location.host + "?BrokerId=" +
AgentInfo.Data.BrokerId +
"&OfficeCode=" +
AgentInfo.Data.OfficeCode;
}
});
console.log($scope.Result)
},
function (error) {
$scope.Error = error.data
})
This blob opens fine in Google Chrome and FireFox. But IE will prompt for open or save. But I would like it to open in the browser. I would appreciate any input in making it open without prompting. Thanks
How about just excluding the if/else statement and just open the ObjectURL in IE as well? Otherwise pdf.js is a alternative if you want to render it in a browser using canvas
Another problem I see with your code is that you are trying to open up a new window with window.open() the problem is that they can become very easy blocked unless it happens within 1 sec after a user interaction event like onclick for example. A xhr.onload is not an user interaction event
So if you are experience some issue like that try doing something like
// Untested, just to give a ruffly idea
btn.onclick = () => {
var win = window.open('', '_blank')
win.document.body.innerHTML = 'loading...'
$http.post(...).then(res => {
var url = URL.createObjectURL(blob)
// redirect
win.location.href = url
})
}
Another thing. Why are you using responseType = arrayBuffer? you could set it to a blob directly...?
I want to pass the input file from content page to extension background script, and then load it with FileReader() in the extension background script.
So in the web page I have a <input type="file"> and from onchange event I pass the file from content script to background page like this:
var myfile = document.getElementById('fileid').files[0];
chrome.runtime.sendMessage({myevent: "start", inputfile: myfile}, function(response) {});
in the background script I have this:
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message.myevent==="start")
{
var reader = new FileReader();
reader.onload = function(e) {
// file is loaded
}
reader.readAsArrayBuffer(message.inputfile);
}
});
but FileReader not load it, I'm not sure if this is correct way , but all i need is to pass the input file element to background script and load it with FileReader to send it with HTTP POST from background script. Please tell me what is wrong or how to do it correctly. It will help a lot if I see a sample code, because I'm new to chrome extension development, and not so experienced.
All messages send through the Chrome extension messaging API MUST be JSON-serializable.
If you want to get the contents of a file at the background page, you'd better create a (temporary) URL for the File object, pass this URL to the background page and use XMLHttpRequest to grab its contents:
// Create URL
var url = URL.createObjectURL(myfile);
// Pass URL to background page (ommited for brevity) and load it..
var x = new XMLHttpRequest();
x.onload = function() {
var result = x.response;
// TODO: Use [object ArrayBuffer]
};
x.open('GET', url); // <-- blob:-url created in content script
x.responseType = 'arraybuffer';
x.send();
Though why do you want to send the file to the background page? Content scripts can also send cross-origin requests.
This works for chrome. You could find the whole production code here.
https://github.com/Leslie-Wong-H/BoostPic/tree/7513b3b8d67fc6f57718dc8b9ff1d5646ad03c75/BoostPic_Chrome/js
main.js:
// Crossbrowser support for URL
const URLObj = window.URL || webkitURL;
// Creates a DOMString containing a URL representing the object given in the parameter
// namely the original Blob
const blobUrl = URLObj.createObjectURL(imageBlob);
console.log(blobUrl);
chrome.runtime.sendMessage(blobUrl, (res) => {
imgUrl = res;
console.log(imgUrl);
clearInterval(refreshIntervalId);
// To prevent that it happens to halt at " Image uploading ..."
setTimeout(() => {
var imgUrlText = document.querySelector(imgUrlTextBoxId);
imgUrlText.value = imgUrl;
}, 1000);
// double check to clear interval to prevent infinite error loop of LoadingStateOne
// Hope it works.
setTimeout(() => {
clearInterval(refreshIntervalId);
}, 500);
console.log("Stop uploading state message");
background.js:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.startsWith("blob")) {
console.log("RECEIVED");
getBase64Url(request).then((res) => {
console.log("Arrived here");
// Acquired from https://stackoverflow.com/questions/18650168/convert-blob-to-base64/18650249#
const reader = new FileReader();
reader.readAsDataURL(res);
reader.onloadend = function () {
const base64data = reader.result;
console.log(base64data);