When I am pressing the download button on my website in Microsoft Edge, I am getting the "Function expected" error.
download() {
this.element = document.getElementById("img") as HTMLElement;
let dataurl = this.element.innerHTML;
let myRegexp = /(?:^|\s)src=(.*?)(?:\s|$)/g;
let match = myRegexp.exec(dataurl);
let match1 = match[1].replace('"></div>', '');
this.ImageURL = match1;
let block = this.ImageURL.split(";");
let contentType = block[0].split(":")[1];
let realData = block[1].split(",")[1];
let file = this.dataURLtoFile(this.ImageURL, 'QRCode.png');
}
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var a = document.createElement("a");
document.body.appendChild(a);
var blob = new Blob([new File([u8arr], filename, { type: mime })], { type: 'mime' }),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = `QRCode.png`;
a.click();
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
return new File([u8arr], filename, { type: mime });
}
The file should download:
Here is the error:
[object Error]: {description: "Function expected", message: "Function
expected", number: -2146823286, stack: "TypeError: Function expected
at n.prototype.dataURLtoFile
(http://instacei.com/1.bb25259c0233e7528077.js:1:237067) at
n.prototype.download
(http://instacei.com/1.bb25259c0233e7528077.js:1:236764) at Anonymous
function (http://instacei.com/1.bb25259c0233e7528077.js:1:155143) at
handleEvent
(http://instacei.com/main.1533bf301f026a959db3.js:1:117135) at
handleEvent
(http://instacei.com/main.1533bf301f026a959db3.js:1:138938) at Lr
(http://instacei.com/main.1533bf301f026a959db3.js:1:87225) at
Anonymous function
(http://instacei.com/main.1533bf301f026a959db3.js:1:93361) at
Anonymous function
(http://instacei.com/main.1533bf301f026a959db3.js:1:284082) at
e.prototype.invokeTask
(http://instacei.com/polyfills.481858ef51fe27531859.js:1:7664) at
onInvokeTask
(http://instacei.com/main.1533bf301f026a959db3.js:1:55627)"}
Related
I have tried the following piece of code, but it is returning everything in a single-column. I need everything to be exactly as it is in the HTML page(It is a grid/table):
let dataType = 'application/vnd.ms-excel';
let extension = '.xls';
let base64 = function(s) {
return window.btoa(unescape(encodeURIComponent(s)))
};
let template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>';
let render = function(template, content) {
return template.replace(/{(\w+)}/g, function(m, p) { return content[p]; });
};
let tableElement = document.getElementById(this.id);
let tableExcel = render(template, {
worksheet: this.name,
table: tableElement.innerHTML
});
this.name = this.name + extension;
if (navigator.msSaveOrOpenBlob)
{
let blob = new Blob(
[ '\ufeff', tableExcel ],
{ type: dataType }
);
navigator.msSaveOrOpenBlob(blob, this.name);
} else {
let downloadLink = document.createElement("a");
document.body.appendChild(downloadLink);
downloadLink.href = 'data:' + dataType + ';base64,' + base64(tableExcel);
downloadLink.download = this.name;
downloadLink.click();
}
The following is output given by above piece of code:
I am doing this by converting data to CSV first and then forwarding data object to this method:
downloadFile(fileName: string, data: any) {
let blob = new Blob([data], {type: 'text/csv'});
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
// save file for IE
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
// save for other browsers: Chrome, Firefox
let objectUrl = URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = objectUrl;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(objectUrl);
}
}
I am getting base64 string from node JavaScript back-end. But it is not working like Chrome.
I can't find any solutions in web. Getting 200 status in API call but it is not downloading file in Firefox while same code working fine with Chrome.
Here is my code::
static downloadFile(fileName: string, fileMimeType: string, uri: string) {
const dataURI = uri;
const blob = this.dataURIToBlob(dataURI);
const url = URL.createObjectURL(blob);
const blobAnchor = document.createElement('a');
const dataURIAnchor = document.createElement('a');
blobAnchor.download = dataURIAnchor.download = fileName;
blobAnchor.href = url;
dataURIAnchor.href = dataURI;
blobAnchor.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
});
};
blobAnchor.click();
}
static dataURIToBlob(dataURI) {
const binStr = atob(dataURI.split(',')[1]),
len = binStr.length,
arr = new Uint8Array(len),
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
for (let i = 0; i < len; i++) {
arr[i] = binStr.charCodeAt(i);
}
return new Blob([arr], {
type: mimeString
});
}
I am getting all the data from Node.js and working fine with Chrome. So I can't find any issue why it is not working with Firefox.
In firefox you have to append your a into DOM and then perform click.
Used document.body.appendChild(blobAnchor); to append into DOM.
Added blobAnchor.className = 'hidden'; so it will not be visible.
And removed from DOM after few seconds with setTimeout(() => blobAnchor.remove(), 300);.
static downloadFile(fileName: string, fileMimeType: string, uri: string) {
const dataURI = uri;
const blob = this.dataURIToBlob(dataURI);
const url = URL.createObjectURL(blob);
const blobAnchor = document.createElement('a');
const dataURIAnchor = document.createElement('a');
blobAnchor.download = dataURIAnchor.download = fileName;
blobAnchor.className = 'hidden';
blobAnchor.href = url;
dataURIAnchor.href = dataURI;
document.body.appendChild(blobAnchor);
blobAnchor.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
setTimeout(() => blobAnchor.remove(), 300);
});
};
blobAnchor.click();
}
static dataURIToBlob(dataURI) {
const binStr = atob(dataURI.split(',')[1]),
len = binStr.length,
arr = new Uint8Array(len),
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
for (let i = 0; i < len; i++) {
arr[i] = binStr.charCodeAt(i);
}
return new Blob([arr], {
type: mimeString
});
}
PROBLEM
My PDF download works in Chrome, but does not work in IE 11/10/9.
In IE, it will prompt me a security warning, but after I click Yes to allow it, nothing happens.
CODE
handleDownload = (reportLoc) => {
var path = reportLoc.item.ReportPath;
$.get("/Api/Apps/GetFileFromServer?filePath=" + path, (response) => {
this.setState({ base64EncodedPDF: response });
}).then(() => {
let a = document.createElement("a");
a.href = "data:application/octet-stream;base64," + this.state.base64EncodedPDF;
a.download = path.substring(path.lastIndexOf("\\") + 1);
a.click();
});
}
Solutions to make it work in both Chrome and IE?
After looking at below 2 references, I managed to solve this problem:
https://blog.jayway.com/2017/07/13/open-pdf-downloaded-api-javascript/
Creating a Blob from a base64 string in JavaScript
My Code now:
handleDownload = (reportLoc) => {
var path = reportLoc.item.ReportPath;
$.get("/Api/Apps/GetFileFromServer?filePath=" + path, (response) => {
this.setState({ base64EncodedPDF: response });
}).then(() => {
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
var byteCharacters = atob(this.state.base64EncodedPDF);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: "application/octet-stream" });
window.navigator.msSaveOrOpenBlob(blob, path.substring(path.lastIndexOf("\\") + 1));
return;
}
let a = document.createElement("a");
a.href = "data:application/octet-stream;base64," + this.state.base64EncodedPDF;
a.download = path.substring(path.lastIndexOf("\\") + 1);
a.click();
});
}
I am trying to covert returned file from server in blob and download it but I am missing smth. file type could be image, pdf or doc.
this is how file response with looks like
$http.get('url', {
headers: {'Content-Type': undefined}
}).then(function (response) {
var blob = new Blob([response.data], { type: 'image' }),
url = $window.URL || $window.webkitURL;
$scope.fileUrl = url.createObjectURL(blob);
}).catch(function(error) {
});
what am I doing wrong and this does not work as expected ?
You just need to use the url directly in an anchor tag
<a ng-href="{{url}}" target='_blank'>Download</a>
If the code above does not work, do this.
function success(response) {
var data = response.data,
blob = new Blob([data], {
type: 'application/octet-stream; charset=UTF-8'
}),
url = $window.URL || $window.webkitURL,
fileUrl = url.createObjectURL(blob);
var anchor = document.createElement('a');
anchor.href = fileUrl;
anchor.target = '_blank';
anchor.download = name;
anchor.style = "display: none";
document.body.appendChild(anchor);
anchor.click();
setTimeout(function() {
document.body.removeChild(anchor);
$window.URL.revokeObjectURL(fileUrl);
}, 100);
}
First convert blob to base64 format
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
var base64data = reader.result;
console.log(base64data);
}
Then use the base64 to download the file
downloadFile(base64data, type, fileName) {
const file = window.btoa(base64data);
const url = `data:${fileType};base64,` + file;
let a = document.createElement('a');
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}
With the following code I have down below. I would like to modify it so that it will convert the blob url variable(url) below into a data url. Javascript Filereader should get the job done, but I would also like to send it to database for storage using ajax call.
Recorder.diplayRecord = function(blob, filename) {
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var displayRecord = document.getElementById("displayRecord");
//link.href = url;
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
var xhr = new XMLHttpRequest;
au.controls = true;
au.src = url;
hf.href = url;
hf.download = 'audio_recording_' + new Date().getTime() + '.wav';
hf.innerHTML = hf.download;
while (displayRecord.lastChild) displayRecord.removeChild(displayRecord.lastChild);
li.appendChild(au);
li.appendChild(hf);
displayRecord.appendChild(li);
Try
Recorder.diplayRecord = function(blob, filename) {
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var displayRecord = document.getElementById("displayRecord");
//link.href = url;
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
var reader = new FileReader();
reader.onload = function(e) {
if (e.target.readyState === 2) {
var _data = e.target.result;
// `POST` `data-uri`
$.post("database/url/", {"data": _data})
.then(
// `success`
function(data, textStatus) {
console.log(textStatus)
}
// `error`
, function(jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown)
})
};
};
reader.readAsDataURL(blob);
au.controls = true;
au.src = url;
hf.href = url;
hf.download = 'audio_recording_' + new Date().getTime() + '.wav';
hf.innerHTML = hf.download;
while (displayRecord.lastChild) displayRecord.removeChild(displayRecord.lastChild);
li.appendChild(au);
li.appendChild(hf);
displayRecord.appendChild(li);
// adding closing `}`
};
See
FileReader
jQuery.post()