Document.createElement Download PDF Not working in IE - javascript

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();
});
}

Related

window.open(url) only open new window with raw text instead of downloading

When I use the following method :
downloadFile(){
const blob = this.b64toBlob(this.formGroup.value.attachment);
const url = window.URL.createObjectURL(blob);
window.open(url);
}
I'm expected it to open a new tab and download the file.
But it's only opening a new tab with raw text content inside.
This is the result I get.
But if I copy/paste the content of the page as an URL, it's working great and my download is starting as expected.
What am I suppose to do to start the download directly.
PS: this is the b64toBlob() method :
b64toBlob(b64Data: string, contentType = '', sliceSize = 512): Blob {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}
Instead of using URL, create a href out of it and you can use the respective click function. Please change the below function of yours something like below and hopefully, you can download the file.
downloadFile(){
var a: any = document.createElement("a");
a.setAttribute('style', 'display:none;');
const blob = this.b64toBlob(this.formGroup.value.attachment);
const url = window.URL.createObjectURL(blob);
a.href = url;
a.click();
}
Sometimes this click won't work properly in IE. In that case you can use msSaveBlob function. The whole function can be changed like,
downloadFile() {
var a: any = document.createElement("a");
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
const blob = this.b64toBlob(this.formGroup.value.attachment);
const url = window.URL.createObjectURL(blob);
a.href = url;
var isIE = /*#cc_on!#*/false || !!(<any>document).documentMode;
if (isIE) {
var retVal = navigator.msSaveBlob(blob, "test"+ '.txt');
}
else {
a.download = "test" + '.txt';
}
a.click();
}
So after few more hours of research...
I managed to get this to work as expected.
Posting the answer if someone end up with the same issue :
downloadFile() {
const blob = this.b64toBlob(this.formGroup.value.attachment);
blob.text().then(result => { // waiting for blob content to be available...
const a: any = document.createElement('a');
a.download = 'test.pdf'; // or whatever your file name is
a.href = result;
a.click();
});
}
The line a.download = 'test.pdf' seem mandatory on chrome but working fine without it for Firefox.
Hope this will help others.

JavaScript Download file from Base64 string not working in IE

Want to save/download Base64 as pdf file using javascript. Below code works in chrome but not in IE. I tried many different ways but not working in internet explorer.
Whats wrong with IE ?
function Base64ToPdf(fileName, base64String) {
const linkSource = "data:application/pdf;base64," + base64String;
const downloadLink = document.createElement("a");
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
}
// Test
var string = 'Hello World!';
var encodedString = btoa(string);
Base64ToPdf("test.pdf", encodedString);
I have tried with https://stackoverflow.com/a/48796495/2247677 which also not works in IE.
I tried many solutions to download Base64 to PDF but not succeeded for IE. Finally I have decided to convert Base64 to Blob first and its working fine in IE 11 and chrome as well.
Full code looks like TS :
export class FileHelper {
static Base64ToPdf(fileName: string, base64String: string) {
if (window.navigator && window.navigator.msSaveBlob) {
const blob = this.Base64toBlob(base64String);
window.navigator.msSaveBlob(blob, fileName);
} else {
const linkSource = "data:application/pdf;base64," + base64String;
const downloadLink = document.createElement("a");
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
}
}
static Base64toBlob(
b64Data: string,
contentType = "application/pdf",
sliceSize = 512
) {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
}
}

Download PDF not working with Firefox using Angular 2 and Node.js

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
});
}

Blob download not triggered on Windows Phone

I'm currently creating something that generates a PDF / CSV file on local and makes it available to download. My current code is working everywhere except on Windows Phone (especially Lumia) which seems to not handle BLOB Url.
How could I fix this issue and force the download?
vm.showPdf = function (documentKey) {
var requestPayloadForShowPdf = {
"DocumentList": documentKey,
"AccountNumber": selectedAccountNumber
};
documentsService.getPdf(requestPayloadForShowPdf).then(function (obj) {
if (!obj.HasErrors) {
vm.isdispalyApiErrorMessage = false;
var byteCharacters = atob(obj.PdfDocument);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new window.Uint8Array(byteNumbers);
var blob = new Blob([byteArray], {
type: 'application/pdf'
});
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, "Statements(" + utilService.getLastFourDigits(selectedAccountNumber) + ").pdf");
} else {
var url = window.URL.createObjectURL(blob);
window.open(url);
}
} else {
vm.isdispalyApiErrorMessage = true;
vm.dispalyApiErrorMessage = utilService.getLiteralFromTranslate('stndrdAPIErrorMsg');//documentsResponse.Errors[0].Description;
}
});
};

Create CSV and open with JS not working in IE, Chrome

I am creating a CSV file from a js object by supplying a filename, comma separated headers, and a data key-value object. However, when I go to download the file, I am facing the following issues:
Chrome: File downloads, but the file is unnamed and has no file extension
IE: File doesn't even download.
Here is my JS code:
function createCSV(filename, headers, data) {
var csvContent = "data:text/csv;charset=utf-8," + headers;
data.forEach(function(d, index) {
var dataString = "";
var i = 0;
for ( var key in d) {
if (d[key] == 'null')
dataString += '\"\"';
else
dataString += "\"=\"\"" + d[key] + "\"\"\"";
if (i < Object.keys(d).length - 1)
dataString += ",";
i++;
}
if (index < data.length)
csvContent += "\n";
csvContent += dataString;
});
var filename = filename + ".csv"
var link = document.createElement("a");
link.setAttribute("href", encodeURI(csvContent));
link.setAttribute("download", filename);
actuateLink(link);
}
function actuateLink(link)
{
var allowDefaultAction = true;
if (link.click)
{
link.click();
return;
}
else if (document.createEvent)
{
var e = document.createEvent('MouseEvents');
e.initEvent('click', true, true);
allowDefaultAction = link.dispatchEvent(e);
}
if (allowDefaultAction)
{
var f = document.createElement('form');
f.action = link.href;
document.body.appendChild(f);
f.submit();
}
}
See fixes for specific browsers below:
function downloadFile(filename, csvContent) {
var blob = new Blob([csvContent]);
var needsClick = true;
var browser = "";
if ( window.webkitURL ) {
browser = "CHROME";
var link = document.createElement("a");
link.setAttribute("href", "data:text/csv;charset=utf-8," + encodeURI(csvContent));
link.setAttribute("target", "_blank");
link.setAttribute("download", filename);
link.click();
} else {
if (document.createEvent) {
browser = "FIREFOX";
var link = document.createElement("a");
link.setAttribute("href", encodeURI("data:text/csv;charset=utf-8," + csvContent));
link.setAttribute("download", filename);
var e = document.createEvent('MouseEvents');
e.initEvent('click', true, true);
needsClick = link.dispatchEvent(e);
}
if(needsClick) {
if(window.navigator.msSaveBlob != undefined){
browser = "IE";
window.navigator.msSaveBlob(blob, filename);
}
}
}
console.log(browser); }
You can fix this problem, at least for Chrome, with the proposed answers to this question.
I do not know an answer for Internet Explorer or any other browser, however.

Categories

Resources