User click on the button on the webpage to download the file, i want to track the file is being downloaded to the user machine or not using client side code like javascript/JQuery.
On button click, ASP.NET .ASHX Web handler code is called which return the file to be downloaded.
Also can we check using javascript/JQuery whether the user is having issue (security, firewall etc.) in downloading the file, when user click on the download button on the webpage.
This can be done via the "progress" event that is attached to an AJAX request.
let xhr = new XMLHttpRequest();
xhr.addEventListener("progress",event=>{
console.log(`${event.loaded} out of ${event.total}`);
});
The download can then be handled via AJAX by creating a false link that links to the file data which will be saved in memory:
xhr.onreadystatechange(function(){
if(this.readyState==4 && this.status==200){
//Download content via imaginary link with data saved in memory
var a = document.createElement('a');
var url = window.URL.createObjectURL(this.response);
a.href = url;
a.download = 'myfile.pdf';
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}else if(this.status==404){
console.error("page not found");
}
});
xhr.open("GET","myfile.pdf",true);
xhr.responseType = "blob";
xhr.send();
Related
I have a page on my website which has a button, that redirects to a URL, that downloads the source code of the git repo for that website. Here is the HTML I have so far:
<!DOCTYPE html>
<html>
<body>
<p>Would you like to download this website's source code?</p>
<button type="button" onclick="window.location.href = 'https://codeload.github.com/SteepAtticStairs/steepatticstairs.github.io/zip/refs/heads/main'">Yes</button>
<button type="button" onclick="window.location.href = '/index.html'">No</button>
</body>
</html>
However, this downloads a file with the name steepatticstairs.github.io-main.zip. I have a bash script that I wrote:
#!/bin/bash
url=https://codeload.github.com/SteepAtticStairs/steepatticstairs.github.io/zip/refs/heads/main
now="$(date '+%m.%d.%Y')"
cd ~/Downloads
wget -O "steepatticstairs.github.io_${now}.zip" $url
Which downloads the file with a name like steepatticstairs.github.io_03.09.2022.zip. This is the name that I want - with the date at the end.
Is there any way that I could replicate this in JavaScript, perhaps using jQuery, where I could click the Yes button and it would download the file from the URL, but it would rename it before download? If someone is able to quickly show me how to also get the date into the filename in JavaScript, that would be awesome, but I would be able to figure that out. I just want to know how to rename the file before downloading.
because cross-domain the ajax will blocked by CORS policy,you need the server to proxy the request and modify the Content-Disposition in the response header, for example: Content-Disposition:attachment;filename= ${filename}.zip
you can use ajax to download file:
const xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.addEventListener('load', () => {
if (xhr.status === 200) {
const a = document.createElement('a');
const url = window.URL.createObjectURL(xhr.response);
a.href = url;
a.download = '${filename}.zip';
a.click()
window.URL.revokeObjectURL(url);
}
});
// if need progress bar can listen progress event
// xhr.addEventListener('progress', e => console.log(e.loaded/e.total))
xhr.open('GET', '${url}')
xhr.send()
In my application written in Ionic 5 and Angular 8, I am in need to download multiple PDF links (file) in the same page on click of the link. I tried but the PDF links are opening in browser. Request to help me achieve this functionality.
https://stackblitz.com/edit/ionic-yzzwov?file=pages%2Fhome%2Fhome.html
The download attribute appears normal when same-origin, otherwise it will appear the same as without download attribute.
list three solutions:
Package the file into a file type that cannot be opened directly by the browser, such as ZIP
Through forwarding by the back end, the back end requests a third-party resource and returns it to the front end, which saves the file using tools such as file-Saver
If the third-party resource the URL points to has CORS configured, you can request the file through XHR
downloadFileXHR(filePath, fileName) {
var xhh = new XMLHttpRequest()
xhh.open('get', filePath)
xhh.responseType = 'blob'
xhh.onreadystatechange = function () {
if (xhh.readyState === 4 && xhh.status === 200) {
var blob = new Blob([xhh.response])
var csvUrl = URL.createObjectURL(blob)
var link = document.createElement('a')
link.href = csvUrl
link.download = fileName
link.click()
}
}
xhh.send()
I'm using this function to download a file:
function download(fileName, data) {
fileName = fileName.replace(/\s+/gi, '_').replace(/[^a-zA-Z0-9-.,_]/gi, '');
let blob = new Blob([data], {type: 'text/plain'});
if(window.navigator.msSaveOrOpenBlob){
window.navigator.msSaveBlob(blob, fileName);
}else{
let elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
// Example usage
$('button').on('click', function(){
download("test.txt", "test");
});
It works perfectly fine. However, it seems to download the file directly into the Downloads folder.
How can I make it open a 'Save As' dialogue instead, so the user can choose his preferred download location?
JSFiddle: https://jsfiddle.net/kbwrcL14/
I've seen suggestions before about manipulating the header like settiing a Content-Disposition -- however is that possible when you generate a file on-the-fly? Afaik headers are what is sent before the HTTP body, but by the time the JS code is running, the entire HTTP request has already finished, and the file is generated by the client itself.
Is there a way to make this work without using http headers?
I am trying to download a file using jQuery. The problem is I have no reference about the file extension. I only know the file name. The file name is unique because it shares the same name with the primary key. So, no file is the same.
This is the jQuery I use:
$("#tbl_surat_all tbody").on('click','.row_surat', function(e) {
var no_s = $(this).find('a').html(); //get the file name
var b_url = $('#base_url').val()+"assets/uploads/surat/"; //base_url
var url = b_url+no_s; //download_url
window.location = url; //script_to_download
});
How do I download the file by only knowing the file name??
Note:
I have no privilage to change table structure, so I can't update the upload script.
The file are images, pdfs, and rars
There is no way to open the file from the server without sending a valid request.
If you don't request the complete file name with extension, you will get an error.
So the only workaround would be to request all possible file extensions.
We could try to include the following:
.jpeg .jpg .png .pdf .rar
And then iterate it with requests.
Since this would open a **** load of windows, we will be immediately closing them, so it will look relatively smooth.
Here is the code:
var url_base='http://127.0.0.1/base_url/file_without_extension';
var ext_arr=['.jpeg', '.jpg', '.png', '.pdf', '.rar'];
for (i=0;i<ext_arr.length;i++){
var url=url_base+ext_arr[i];
window.open(url)
.addEventListener('load', function(){
this.close();
}, false);
}
Note: do note that in order for it work properly, requested files must meet the same origin policy.
Edit: I have modified the above code to load resources in background via xhttp requests and then output it directly for download.
This method should work flawlessly for all types of files, and it's also the fastest!
var url_base='http://127.0.0.1/';
var file_name='file_without_extension';
var ext_arr=['.jpeg', '.jpg', '.png', '.pdf', '.rar'];
for (i=0;i<ext_arr.length;i++){
// Define request url
var url=url_base+file_name+ext_arr[i];
// Use XMLHttpRequest instead of Jquery $ajax
var xhttp = new XMLHttpRequest();
// Set the url as a property
xhttp['user_filename']=file_name;
// Bind on ready function
xhttp.onreadystatechange = function() {
var a;
// Check if page has loaded successfully
if (this.readyState === 4 && this.status === 200) {
// Trick for making downloadable link
a = document.createElement('a');
a.href = window.URL.createObjectURL(this.response);
// Filename for downloading
a.download = this.user_filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
a.parentNode.removeChild(a);
}
};
// Set request url and method
xhttp.open("GET", url);
// Set responseType as blob for binary response
xhttp.responseType = 'blob';
// Send request
xhttp.send();
}
I have a JavaScript Pivot table that displays data to the user. The user can select the columns/rows etc. I've added an export to Excel button, that performs an ajax post with the current data/view of the pivot table (json data). It posts the data to my server that converts that to an Excel file.
Creating the file all works well, but my problem is getting the file to the user. From what I've read I can't send a file to a user after an ajax post.
I'm happy to use a plain html post (in fact it is what I want since I can redirect the user to the file), but I don't know how to include the pivot table data as part of the post since it is not a form.
I know I can save the file locally and send a url back but this complicates things and I would like to avoid it.
Is it possible to do this without saving the file locally and sending a url where the file is located?
Browsers don't (yet) support JSON serialization of forms, so AFAIK it's not really possible to send JSON to backend using pure forms.
I have two solutions that will not require saving file on the server:
1) Simple solution would be to generate an invisible form with JavaScript, create hidden input of name json and populate it with JSON content to send to the server. On the server side, you would read the form data and parse JSON that is stored in the data. Then you just generate the file and send the file in response. The browser should trigger download dialog.
var form = document.createElement('form');
form.method = 'post';
form.action = 'url';
var input = document.createElement('input');
input.type = 'hidden';
textarea.name = 'json';
textarea.value = JSON.stringify(your_json);
form.appendChild(input);
document.body.appendChild(form);
form.submit();
form.parentNode.removeChild(form);
2) Second option uses ajax to send data to the server. The browsers need to support several APIs, though.
You do your JSON request as usual and the server should respond with header Content-Type: here-the-MIME-type-of-your-file and with the file contents in response body.
The code on client side should look like:
var json = JSON.stringify({here: ['your', 'json', 'to', 'send', 'to', 'server']});
var xhr = new XMLHttpRequest();
xhr.open('POST', '/your/api/url', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.responseType = 'arraybuffer';
xhr.addEventListener('load', function () {
var blob = new Blob([this.response], { // reading response, not responseText
type: this.getResponseHeader('Content-Type')
});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = 'file_name.txt'; // set proper extension
document.body.appendChild(a); // it needs to be added to the document in order to work
a.click();
a.parentNode.removeChild(a);
});
xhr.send(json);
Also, the created URL objects should be revoked at some point, otherwise they will exist until the page reloads. But I think they cannot be revoked before the user downloads the file. So it's one task still to do with the above code.