How to detect download complete in javaScript - javascript

I want to execute two operations in one javaScript function
force download of a csv file
send an ajax request to mark records in table that records were downloaded.
Since both of these operations will present the user with prompts and dialogue boxes, I want to delay execution of the 2nd event until the first event is complete.
When the user opens the page, they are presented with a list of current records. They check records they wish to process. The checked records are then packaged and the user is presented with the download "Save" or "Open" box. when that operation is complete then the ajax request should execute.
My thought was I could detect when "a" was removed from the document. But I'm not sure how I would do that.
Here is my code for the download
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob(exportArray, {type: 'text/csv'}));
a.download = 'jobCostHandOff.csv';
// Append anchor to body.
document.body.appendChild(a)
a.click();
// Remove anchor from body
document.body.removeChild(a)

I have implemented such a mechanism in a web application with the following workflow:
the user selects a file on their computer
they configure options of the app
they click the submit button
a loader starts animating client-side
the browser send the entire form to the server for processing
the processing (which is actually about converting a guitar score to a tablature) yields a text/plain file, which is stored on the server (but not sent yet): a small JSON with the link to the generated file is sent back. That JSON data represents either success or error. In the case of error, the message is displayed to the user. In the case of success, the status field is set to OK and the payload contains the link to the file.
the JS code handling the AJAX call, upon success, triggers the download.
the browser presents the user with the usual (e.g. in Firefox) "open or save file" dialog
the web app detects the opening of the dialog and hides the loader.
It seems pretty similar to your need.
The gist of the solution is this:
triggering the file download is done by setting the src attribute of an iframe hidden in the page
the server sends a cookie in response to the request for the file to be downloaded
a JS code on a timer inspects the cookies of the document (which, very fortunately, includes the cookies to the iframe) and upon seeing "the Holy cookie", knows for sure that the file download has started, which is the only event the code can grab.
Quickly looking through the PHP code of my web app, I see this:
// This cookie is for the jQuery.fileDownload plugin
header('Set-Cookie: fileDownload=true; path=/');
You have the name of the JS code that does the last bullet point item in the code comment :-) Another reason among the myriad of reasons why I write commented code...
HTH.

Related

Workaround for Error 414 when opening file from PHP script

I have a PHP script that's outputting a CSV file and up until now I've been just using a link and passing parameters that are used to determine the output in the GET data. However recently the size of the data increased and now that code gets Error 414 - Request URI too Large. I tried using a hidden form to do it with POST but it just reloaded the page and didn't supply a prompt to download the file and all of the suggestions I've been able to find online about doing it with AJAX suggest using a link with GET data instead. Does anyone know a workaround that will have the browser still let the user easily download the data?
Presently I'm just setting the href attribute of a <a> tag.
$("#exportCSV").attr('href', "myscript.php/?data=" + exportData);
exportData has become too long for GET data but I want to maintain the behavior where if you click on a link that has say a CSV file being outputted the browser provides a download dialog for the user.

Find out when document.location.href has been completed

I have a button that lets users download a file.
The file is returned from the server in the Response (binaries set as attachment), and I am letting the browser handle the file download from there on out.
Im doing the following on button click:
var fileUrl = 'mysite.com?id=12345';
document.location.href = fileUrl;
This will load the file, however, it can take a couple of seconds. I would like to show a preloader but then ofcourse I have to know when the file has been downloaded completed. Since I'm staying on the same page, is there a method or callback that tells if the 'new' location is loaded and thus I can hide the preloader?
Thanks!
Assuming you can download the file twice, you could load the file in a hidden iframe and detect when the iframe is done loading. Then, the file is already cached and should download quickly.

JavaScript retrieve window handle from target=_blank submitted form

I'm trying to create an automated script that lets me download various files from a website, then upload them to a new website. The script will let multiple users copy content from the old site to the new one at the same time.
I initially attempted to use AJAX to download one file at a time, and store the file(s) data in variables, then upload this variable (file data) to the second domain. The download worked fine, but the PHP page on the second domain always threw back a 500 request error message AFTER uploading, despite setting various file size parameters and processing time parameters in PHP. This meant I couldnt even see what was echoed by the PHP page to debug, and continue developing that method.
After spending a long time trying to fix this (and failing miserably), I decided to just let the users download the old files normally, then use a form to upload the files. As I want the script to continue to run whilst the file is uploading, I've decided to set the forms target to "_blank" to open a new tab (which uploads the file).
How can I retrieve the windows handle that's opened with the target="_blank" form, to test when the window is closed? I don't need to access the windows HTML, I just want to check when it closes. The page that's opened by the form is not on the same domain as the form that opens it, but the "Access-Control-Allow-Origin" header is set to "*" on the second domains PHP page.
I don't think you can retrieve the window handle, but you can use Javascript to keep a reference to the window and check whether the window is closed or not. You would have to open your window with Javascript like this
var uploadWindow = window.open("http://www.google.com");
Then you can use a function on a timer to monitor if the window has closed or not:
var interval = 250;
setTimeout(checkClose, interval);
function checkClose() {
if (uploadWindow.closed) {
// Code to run when window is closed
}
else {
setTimeout(checkClose, interval);
}
}
I hope this can be of help

Ajax/Javascript - File Download

Client (Request through XMLHttpRequest) -> Server.
Server [Builds CSV and prints it on the output stream of response] -> Client.
Now step 3 should be-> Client's browser should show a download dialogue (save, open and cancel). Since the content type is plain text from the server, and the content disposition is not set, can we create a file using javascript and prompt the user to download?
I know this question is slight stupid. But there is no other option. I have to do it this way.
Changing in the server side script will make it a one minute task. But I have to do it in the client side. The responseText property of the XMLHttpRequest object will be plain text and I have to show download prompt for the text file.
Is this possible?
Not that I'm aware of. But you could just use location.href (or a form, if POST data is needed) to request the server-side file. With the correct headers (Content-Disposition: attachment and I think there's another one) you can have the response be downloaded rather than displayed.
EDIT: Even better, use an iframe that's hidden. That way, you can still do a fancy "Loading, please wait" thing in the main page.
Theoretically it could be possible, by using Data URI's
<a download = "yourfile.csv" href="data:application/octet-stream;charset=YOURCHARSET;base64,BASE64allthedata">Generate</a>

how to download client side content

I want to let the user download the current content of a textarea into a text file on their computer. In the past I would create an iframe pointing to a URL with the data, which would trigger a file download dialog. However this time the data is client side.
So, is it possible to let the user download data without sending it server side?
If it does not need to work in "old browsers" like IE, you could open a new window with the location 'data:text/plain,' + yourTextarea.value. The user can then save that file using the File/Page menu or Ctrl+S.
is it possible to let the user download data without sending it server side?
In the general case no.
It is possible with a data: URL, as in janmoesen's answer (although you should be URL-encoding the value to include in the URL, or you may face corruption when a %nn sequence appears in the data).
However, this becomes impractical for very long data, and it's not available in old browsers or IE. (IE8 allows short data URLs to be used for images, but not direct navigation.) So whilst you can include a data-URL method to enhance the process on browsers that support it, you will still need a fallback solution of sending a formful of the data to the server side and having it spit back a file in response.
(For security reasons, this should only be allowed in a POST request, and the server should include Content-Disposition: attachment in the response. A content-echo script can give you cross-site-scripting problems otherwise.)
Check out how File and Blob types work.
You can create one and trigger a download programmaticaly:
https://www.bennadel.com/blog/3472-downloading-text-using-blobs-url-createobjecturl-and-the-anchor-download-attribute-in-javascript.htm
https://blog.logrocket.com/programmatic-file-downloads-in-the-browser-9a5186298d5c/

Categories

Resources