I am trying to download multiple files from multiple URL's using javascript so far I have tried multiple options but it works only for 1 URL.
I have an array of URL's that needs to start multiple downloaded in the browser.
$(fileUrls).each(function(_index, fileUrl: any) {
let tempElement: any;
tempElement = document.createElement("A");
tempElement.href = fileUrl;
tempElement.download = fileUrl.substr(fileUrl.lastIndexOf("/") + 1);
document.body.appendChild(tempElement);
tempElement.click();
document.body.removeChild(tempElement);
});
Also tried using
$(fileUrls).each(function (_index, fileUrl: any) {
window.location.href = fileUrl;
});
But it works for only 1 URL rest of the calls fails with below warning message in the browser
Resource interpreted as Document but transferred with MIME type application/octet-stream
You can achieve this using below code.
create one array and pass all the file locations which you want to
download like below.
var files= [
'file1_Link',
'file2_Link',
'file3_Link'
];
function to download all the files. we are creating the anchor tag
with download attribute and on loop we need to click on that link.
please see below ex.
function downloadAll(files){
if(files.length == 0) return;
file = files.pop();
var theAnchor = $('<a />')
.attr('href', file[0]) // set index accordingly
.attr('download',file[0]) // set index accordingly
// Firefox does not fires click if the link is outside
// the DOM
.appendTo('body');
theAnchor[0].click();
theAnchor.remove();
downloadAll(files);
}
// call the function like below to achieve your goal
downloadAll(files);
Related
In my application, i am trying to download html of current page which is with same domain name. I have written some method to download the html and it is downloading.
But, i have tried to open it in chrome as well as edge and it is not opening. But, in IE it is opening and displaying text of noscript tag (We're sorry but app doesn't work properly without JavaScript enabled.Please enable it to continue.).
I am inputting intranet site URL and clicking the download button. Here is my method below.
downloadHtml() {
let url = this.urlInput; // input text v-model value
fetch(url)
.then((res) => res.text())
.then((html) => this.downloadAsFile("report.html", html)); // by this name it is downloading
},
downloadAsFile(name, text) {
const link = this.createDownloadableLink(name, text);
const clickEvent = new MouseEvent("click");
link.dispatchEvent(clickEvent);
},
createDownloadableLink(fileName, content) {
let link = document.createElement("a");
link.href = 'data:attachment/text,' + encodeURIComponent(document.documentElement.outerHTML);
link.target = '_blank';
link.download = fileName;
return link;
},
**The problems are :
1. The app root signifies the public/index.html and that downloaded html is this one not the current page's html.
2. Chrome or Edge is not opening that html page even i checked browser is javascript enabled.
So, what i have to change the download the current page html?
The problem is that an HTML file in not an application/octet-stream file type. The mime type of an HTML page is text/html
I'm unsure of the way you try to create your download link. I don't have time to test it, but there is the way I do it usually using the createObjectURL API :
async function fetchHTML(url) {
let content = await fetch(url).then(resp => resp.text());
let file = new Blob([content],{type:'text/html'});
let href = window.URL.createObjectURL(file);
let a = document.createElement('a');
a.href = href;
a.setAttribute('download', 'report.html');
document.body.appendChild(a);
a.dispatchEvent(new MouseEvent('click'));
}
Another problem is that you don't append your link into the DOM in the code you provided. So the DOM cannot trigger your mouse event and so starting the download (it's needed by some browsers).
With the good mime type, the file in a proper format and a link in to the dom, it should be ok.
I want to rename a blob file downloaded from a server. I looked for other solutions but they mainly deal with the created anchor link and setting name to anchor. I tried this approach:
getRenamed(title): void {
this.docTitle = title;
this.requestService.download(title).subscribe((response) => {
let thefile = new Blob([response], {
type:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
let url = window.URL.createObjectURL(thefile);
window.open(url);
});
}
But the problem with this approach is that it creates a random filename. And I want to give it a specific filename.
I have made a user interface to fetch data from a MySQL table and visualize it. It is running on a bokeh server. My users connect remotely to the server using their browser (firefox). This works perfectly fine: I simply import the table into a pandas dataframe.
My users also need to download the table as excel. This means I cannot use the export_csv example which is pure javascript.
I have no experience with JavaScript. All I want is to transfer a file from the directory where my main.py is to the client side.
The technique I have tried so far is to join a normal on_click callback to a button, export the information I need to 'output.xls', then change a parameter from a dummy glyph which in turn runs a Javascript code. I got the idea from Bokeh widgets call CustomJS and Python callback for single event? . Note I haven't set the alpha to 0, so that I can see if the circle is really growing upon clicking the download button.
At the bottom of my message you can find my code. You can see I have tried with both XMLHttpRequest and with Fetch directly. In the former case, nothing happens. In the latter case I obtain a file named "mydata.xlsx" as expected, however it contains only this raw text: <html><title>404: Not Found</title><body>404: Not Found</body></html>.
Code:
p = figure(title='mydata')
#download button
download_b = Button(label="Download", button_type="success")
download_b.on_click(download)
#dummy idea from https://stackoverflow.com/questions/44212250/bokeh-widgets-call-customjs-and-python-callback-for-single-event
dummy = p.circle([1], [1],name='dummy')
JScode_xhr = """
var filename = p.title.text;
filename = filename.concat('.xlsx');
alert(filename);
var xhr = new XMLHttpRequest();
xhr.open('GET', '/output.xlsx', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
alert('seems to work...');
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, filename);
}
else {
var link = document.createElement("a");
link = document.createElement('a');
link.href = URL.createObjectURL(blob);
window.open(link.href, '_blank');
link.download = filename;
link.target = "_blank";
link.style.visibility = 'hidden';
link.dispatchEvent(new MouseEvent('click'));
URL.revokeObjectURL(url);
}
}
else {
alert('Ain't working!');
}
};
"""
JScode_fetch = """
var filename = p.title.text;
filename = filename.concat('.xlsx');
alert(filename);
fetch('/output.xlsx').then(response => response.blob())
.then(blob => {
alert(filename);
//addresses IE
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, filename);
}
else {
var link = document.createElement("a");
link = document.createElement('a')
link.href = URL.createObjectURL(blob);
window.open(link.href, '_blank');
link.download = filename
link.target = "_blank";
link.style.visibility = 'hidden';
link.dispatchEvent(new MouseEvent('click'))
URL.revokeObjectURL(url);
}
return response.text();
});
"""
dummy.glyph.js_on_change('size', CustomJS(args=dict(p=p),
code=JScode_fetch))
plot_tab = Panel(child=row(download_b,p),
title="Plot",
closable=True,
name=str(self.test))
def download():
writer = pd.ExcelWriter('output.xlsx')
data.to_excel(writer,'data')
infos.to_excel(writer,'info')
dummy = p.select(name='dummy')[0]
dummy.glyph.size = dummy.glyph.size +1
Trying out Eugene Pakhomov's answer, I found what was the issue.
The javascript code I named JScode_fetch is almost correct, however I get a 404 because it is not pointing correctly to the right path.
I made my application in the directory format: I changed my .py file to main.py, placed it into a folder called app, and changed this one line of code in JScode_fetch:
fetch('/app/static/output.xlsx', {cache: "no-store"}).then(response => response.blob())
[...]
You can see the problem was that it was trying to access localhost:5006/output.xlsx, instead of localhost:5006/app/output.xlsx. As it is in directory format, the right link is now localhost:5006/app/static/output.xlsx to count for the static directory.
I also changed a few lines in the download function:
def download():
dirpath = os.path.join(os.path.dirname(__file__),'static')
writer = pd.ExcelWriter(os.path.join(dirpath,'output.xlsx'))
writer = pd.ExcelWriter('output.xlsx')
data.to_excel(writer,'data')
infos.to_excel(writer,'info')
dummy = p.select(name='dummy')[0]
dummy.glyph.size = dummy.glyph.size +1
Now it is working flawlessly!
edit: I have added , {cache: "no-store"} within the fetch() function. Otherwise the browser thinks the file is the same if you have to download a different dataframe excel while using the same output.xlsx filename. More info here.
bokeh serve creates just a few predefined handlers to serve some static files and a WebSocket connection - by default, it doesn't have anything to serve files from the root of the project.
Instead of using the one-file format, you can try using the directory format, save your files to static directory and download them from /static/.
One downside of this approach is that you still have to write that convoluted code to just make your backend create the file before a user downloads it.
The best solution would be to go one step further and embed Bokeh Server as a library into your main application. Since you don't have any non-Bokeh code, the simplest way would be to go with Tornado (an example).
bokeh.server.server.Server accepts extra_patterns argument - you can add a handler there to dynamically create Excel files and serve them from, say, /data/. After all that, the only thing that you need in your front-end is a single link to the Excel file.
First of all let me clarify that what I'm trying to do is for locally use only, users will have direct access to the html page.
What I'm trying to do is basically append and save text to an HTML file.
This is what I have.
HTML (index.html)
<div id="receiver"></div>
<button id="insertButton">Insert</button>
JS
$(document).ready( function() {
$('#insertButton').click(function(){
$('#receiver').append('<h1>Hi,</h1>','<p>How are you?</p>');
})
});
What I don't know is how to save the file (index.html) after the appending. Any idea how to do that? Is this even possible with Javascript or jQuery?
You could change your handler to do this:
$(document).ready( function() {
$('#insertButton').click(function(){
$('#receiver').append('<h1>Hi,</h1>','<p>How are you?</p>');
// Save the page's HTML to a file that is automatically downloaded.
// We make a Blob that contains the data to download.
var file = new window.Blob([document.documentElement.innerHTML], { type: "text/html" });
var URL = window.webkitURL || window.URL;
// This is the URL that will download the data.
var downloadUrl = URL.createObjectURL(file);
var a = document.createElement("a");
// This sets the file name.
a.download = "source.htm";
a.href = downloadUrl;
// Actually perform the download.
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
})
});
You should take a look at the compatibility matrix and documentation of URL over at MDN. Notably URL is not available for IE 9 or earlier. Same for Blob.
If I understand it correctly, you need it on local machine and for temporary usage then you can store it in cookies.
So whenever you load the page, check if cookie available, if yes then load data from cookies or load the fresh data.
You can use this data, unless and until cookies are not cleared.
Hope this helps...
Don't need any javascript. After the html is appended, just press Ctrl+S to save the file locally with modified html.
This question already has answers here:
How to create a file in memory for user to download, but not through server?
(22 answers)
Closed 6 years ago.
Typically, HTML pages can have link to documents (PDF, etc...) which can be downloaded from the server.
Assuming a Javascript enabled webpage, is it possible to dynamically create a text document (for example) from within the user browser and add a link to download this document without a round trip to the server (or a minimal one)?
In other word, the user would click on a button, the javascript would generate randoms numbers (for example), and put them in a structure. Then, the javascript (JQuery for example) would add a link to the page to download the result as a text file from the structure.
This objective is to keep all (or at least most) of the workload on the user side.
Is this feasible, if yes how?
Here's a solution I've created, that allows you to create and download a file in a single click:
<html>
<body>
<button onclick='download_file("my_file.txt", dynamic_text())'>Download</button>
<script>
function dynamic_text() {
return "create your dynamic text here";
}
function download_file(name, contents, mime_type) {
mime_type = mime_type || "text/plain";
var blob = new Blob([contents], {type: mime_type});
var dlink = document.createElement('a');
dlink.download = name;
dlink.href = window.URL.createObjectURL(blob);
dlink.onclick = function(e) {
// revokeObjectURL needs a delay to work properly
var that = this;
setTimeout(function() {
window.URL.revokeObjectURL(that.href);
}, 1500);
};
dlink.click();
dlink.remove();
}
</script>
</body>
</html>
I created this by adapting the code from this HTML5 demo and messing around with things until it worked, so I'm sure there are problems with it (please comment or edit if you have improvements!) but it's a working, single-click solution.
(at least, it works for me on the latest version of Chrome in Windows 7)
By appending a data URI to the page, you can embed a document within the page that can be downloaded. The data portion of the string can be dynamically concatenated using Javascript. You can choose to format it as a URL encoded string or as base64 encoded. When it is base64 encoded, the browser will download the contents as a file. You will have to add a script or jQuery plugin to do the encoding. Here is an example with static data:
jQuery('body').prepend(jQuery('<a/>').attr('href','data:text/octet-stream;base64,SGVsbG8gV29ybGQh').text('Click to download'))
A PDF file? No. A txt file. Yes. With the recent HTML5 blob URIs. A very basic form of your code would look something like this:
window.URL = window.webkitURL || window.URL;
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
var file = new window.BlobBuilder(),
number = Math.random().toString(); //In the append method next, it has to be a string
file.append(number); //Your random number is put in the file
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file.getBlob('text/plain'));
a.download = 'filename.txt';
a.textContent = 'Download file!';
document.body.appendChild(a);
You can use the other methods mentioned in the other answers as a fallback, perhaps, since BlobBuilder probably isn't supported very well.
Demo
Note: BlobBuilder seems to be deprecated. Refer to this answer to see how to use Blob instead of BlobBuilder. Thanks to #limonte for the heads up.