Large file downloads don't work in Firefox browser - javascript

I have a Angular app where users can download some documents(.jpg, .mp4 and .pdf) that they uploaded. Basically the download of the file works in this way: A service is called which returns some information about the file as name, type, size and the content of it in base64.
This is the download method in Component when the user clicks on the download button:
downloadDocument(doc: Document) {
this._subDownDocument = this.service.getDocument(doc).subscribe((resp: Document) => {
var link = document.createElement("a");
link.download = resp.fileName;
link.target = "_blank";
// Construct the URI
link.href = resp.url;//Url is the content of the file in base64
document.body.appendChild(link);
link.click();
// Cleanup the DOM
document.body.removeChild(link);
});
}
It's working perfectly for files up to 12mb. But when files are bigger the download doesn't start, the service brings the file correctly but I don't know why the download doesn't start. No error is shown in the browser console.
This problem only happens with Firefox because in Google Chrome it works fine. Any idea on how can I solve this?

I solved this by installing FileSaver.js. It's used for large files purposes.
npm install file-saver --save
And changed my download method to:
downloadDocument(doc: Document) {
this._subDownDocument = this.service.getDocument(doc).subscribe((resp: Document) => {
//Url is the content of the file in base64
fileSaver.saveAs(this.b64toBlob(resp.url, resp.type), resp.fileName);
});
}
private b64toBlob(dataURI, type) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: type });
}

Related

cannot download file from BlobUrl (using MediaReader)

I have the following code:
let self = this;
this.chunks = [];
const canvas2 = document.getElementById("self-canvas");
let recordStream = canvas2.captureStream(1);
var options;
options = {mimeType: 'video/webm; codecs=vp9'};
this.recorder = new MediaRecorder(recordStream, options);
this.recorder.ondataavailable = function(evt) {
self.chunks.push(evt.data);
};
this.recorder.onstop = function(evt) {
console.log("recorder stopping");
const link = document.createElement('a');
const videoBlob = new Blob(self.chunks, { type: "video/webm" });
console.log("file size: " + videoBlob.size);
const url = URL.createObjectURL(videoBlob);
link.href = url;
link.download = "sample.webm";
document.body.append(link);
link.click(); //if I comment out here I can see the video
};
console.log("finished setting controller")
console.log("recorder starting");
this.recorder.start(10000);
// the recorder.stop is called somewhere else
What it is supposed to do is pretty simple:
I have the element with id "self-canvas" that is showing my camera.
Now I am trying to record the camera and download the video from the browser using MediaRecorder, but for some reason I am unable to download the file.
I am sure that the file is being recorded, and console.log("file size: " + videoBlob.size); does not return empty.
But when I let the code run, instead of downloading the file, it tries to open it on the same window, and I cannot even see the video because the previous window disappears with the data of the recording.
However if I comment out the link.click(); I am able to see the video by opening the link on a new page (without closing the previous one). But it still doesn't download...
I used this as example, what am I doing wrong?
For heaven's sake...
I just added target blank and it worked.
link.href = url;
link.download = "sample.webm";
link.target = '_blank';
Probably because the resources are lost if it tries to open on the same page, and because it doesn't actually download the file if it is not a link "click".
Still, I never saw anyone having to add target blank in their examples like this one.
So I wonder why this is the case only for me...

Why cannot python call Javascript() from within a python function?

I used the code suggested from Download CSV from an iPython Notebook to dynamically build the javascript code and pass it to the browser using Javascript() in python when called from a jupyter notebook. Code works great. If I embed the same code in a python function and call the python function from the same jupyter notebook, the call Javascript() in python no longer works. How can I make the reusable function work?
I am trying this on Chrome Version 73.0.3683.103 (Official Build) (64-bit) running on Windows 10. Apologies if already answered. I have scoured SO and google.
This works..
from IPython.display import Javascript
js_download = """
var csv = '%s';
var filename = 'results.csv';
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
""" % data_in_dataframes.to_csv(index=False).replace('\r','\\r').replace('\n','\\n').replace("'","\'")
Javascript(js_download)
This does not work, it fails to execute Javascript(js_download), but neither does it give any error that I can see in the jupyter notebook nor the java console in the browser. It is as if it never executed Javascript(js_download).
from IPython.display import Javascript
def js_download_csv(df_download, s_filename='results.csv'):
js_download = """
var csv = '%s';
var filename = '%s';
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
""" % (df_download.to_csv(index=False).replace('\r','\\r').replace('\n','\\n').replace("'","\'"), s_filename)
Javascript(js_download)
return None
js_download_csv(df_download, s_filename)
Apologies if I have left anything obvious out. I can find no errors or logs with any information regarding what is happening.
Any suggestions welcome.
I have found a partial answer, in that while I do not why this problem occurs, I have found how to overcome it. In https://medium.com/#tomgrek/reactive-python-javascript-communication-in-jupyter-notebook-e2a879e25906 we see in the article the following gotcha:
A big gotcha: something somewhere needs to return Javascript as its output, otherwise it doesn’t get executed in the notebook.
So, if we change the code to the following (i.e. return the Javascript call), it works.
from IPython.display import Javascript
def js_download_csv(df_download, s_filename='results.csv'):
js_download = """
var csv = '%s';
var filename = '%s';
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
""" % (df_download.to_csv(index=False).replace('\r','\\r').replace('\n','\\n').replace("'","\'"), s_filename)
return Javascript(js_download)
js_download_csv(df_download, s_filename)

Prevent OPEN file prompt in microsoft edge using angular js

I have a code in angular js which downloads an excel file on clicking a button. In chrome the file download starts automatically on clicking the button. But on Microsoft Edge clicking the button displays a prompt asking the user, whether they want to open or save file. Clicking on save button in prompt shows yet another prompt with 3 buttons OPEN, OPEN FOLDER and VIEW DOWNLOADS.
I know that edge provides settings options to disable the prompt on each download.
But is there any way on edge to start download but after downloading it does not show the second prompt asking what to do, using angular js or jquery?
The code for downloading file is as follows:
var fileName;
var a = document.createElement("a");
document.body.appendChild(a);
var type = headers('Content-Type');
var disposition = headers('Content-Disposition');
if (disposition) {
var match = disposition.match(/.*filename=\"?([^;\"]+)\"?.*/);
if (match[1])
fileName = match[1];
}
var blob = new Blob([data], {
type: type
}),
url = window.URL.createObjectURL(blob);
if (blob.size == 0) {
return;
}
a.href = url;
a.download = fileName;
var isIE = false || document.documentMode || /Edge/.test(navigator.userAgent); //if browser is IE and Edge
if (isIE) {
window.blur();
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
a.style = "display: none";
a.click();
window.URL.revokeObjectURL(url);
}

Can't open blob files in firefox

I want to open files sent from server on Firefox.
Actually it's working on IE. Here's how I would proceed:
openFile(path, fileName) {
this.creditPoliciesService
.openFile(path)
.toPromise()
.then(data => {
var blob = new Blob([data.body], { type: "application/pdf" });
if (window.navigator && window.navigator.msSaveOrOpenBlob) { //if navigator is IE
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else { // Mozilla case
var fileURL = URL.createObjectURL(blob); //URL.createObjectURL takes only one parameter.
window.open(fileURL);
}
});
}
When I open file I get in new tab a blob adress blob:http://localhost:4200/90907276-947a-47d8-873d-40163 with an empty page
I think I should pass file name but it's not possible with URL.createObjectURL
How can I open files in right format ?
in Chrome : files get opened but without a file name at the top bar, I get "XXXXXX" instead.
in Firefox : as mentioned I get blob address at the navigation bar with an empty page.
in IE : it's working

Internet Explorer - The data area passed to a system call is too small - Downloading png with the uri

I am trying to download a png file using the uri (code below). It works in Chrome, Firefox and Safari - but not (of course) in Internet Explorer. I am on Windows 7, so I am using IE11 in Edge Document Mode. The error is "The data area passed to a system call is too small." I've read in this MDN post
IE9 and later, as well as Edge, supports data URIs in CSS and JS
files, but not in HTML files, with a max size of 4GB.
My URI is only 1410 bytes (using uri.length). Any ideas why I am getting the error with data of this size and how to fix it?
The download function:
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
The uri format:
"data:image/png;base64,iVBORw0KGgo ETC..."
The solution is below. I can't seem to find the link to give credit, but this solved it. Instead of converting the canvas to a uri first, I pass the canvas and either convert to a uri and download using a link or (for IE) I convert to a blob and use canavas.msToBlob() and msSaveBlob()
function downloadURI(canvas, name) {
if (navigator.msSaveBlob) { // IE10+
var blob = canvas.msToBlob();
return navigator.msSaveBlob(blob, name);
} else {
var uri = canvas.toDataURL("image/png")
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
if (link.click) {
link.click();
} else {
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window);
link.dispatchEvent(event);
}
document.body.removeChild(link);
}
}

Categories