Showing page load progress with JavaScript - asp.net

I am retrieving a list of files from a web service and displaying them as links. When someone clicks on the link, the file should start downloading. The problem is that no direct access to the file exists. Here is the process to download a file:
User clicks on link
Server calls web service to retrieve file
Browser is loading for as long as it takes to bring the file back from the web service
Browser finally offers file to user for download
To counter the unfavorable user experience of having to wait for the web service before the download starts, I would like to display a "Loading..." feedback dialog when a link is clicked, and have the dialog go away when the file is ready.
I am using jQuery, and have been playing around with adding an iframe to the page to load the file, but the problem I am having is I don't know how to determine that the file is ready.
I am looking for tips, not only on the client side to give ample feedback, but perhaps also on the server side (using ASP.Net), just in case I can do something to streamline the process. Thank you.
Update: To clarify, this is for downloading a file to a user's machine. What I'm specifically looking for is a way to determine when the file is ready for download. So, when step #4 above takes place, I'd like to remove the "Loading..." message.

It sounds like you need to expose a new request URL on your server, whose only job is to reply whether the web-service-retrieval has completed (or if not, how far it has got).
Have AJAX poll that service every few seconds, and remove the "Loading..." message when it replied that the file is ready.
The client should send the session ID (maybe also a file ID), so that the server knows which file is being asked about. The server side will need to be able to contact the running web-service-retrieval process/thread to ask it how far it got. (If it can't find the thread then presumably it has finished.)

you can use the complete option for $.ajax function in jquery which should get called when the request completes

You can have jQuery to wait for the click of the link and when the link is clicked show the display loading message.
Example that shows how to 'Loading - Please wait' Message Display Script you can follow.
EDIT-
Basically you want a progress bar monitor, which I have never seen it done with just javascript, but with flash or ajax.
Here is a File Upload Demo that should help.

If you're linking to an ASHX that is grabbing the file and writing it back to a stream, you can modify the links click event to display a message.
$(function () {
$("a.someClass").click(function () {
$("div.message").fadeIn(); // show a loading message
return true; // make sure the link still gets followed
});
});
The loading message can just be a spinner or something while waiting for the ASHX to write the response back.
Edit: Since you're not directly linking to the ASHX:
$(function () {
var ashxCallback = function (data, textStatus) {
// data could be: xmlDoc, jsonObj, html, text, etc...
this; // the options for this ajax request
// textStatus can be one of: "timeout", "error", "notmodified", "success", "parsererror"
alert(textStatus);
};
$("a.someClass").click(function () {
$("div.message").fadeIn(); // show a loading message
$.get("some.ashx?id=1234", "", ashxCallback);
return false;
});
});
Using jQuery.get() and jQuery.post().
Edit #2: I just had another thought. What if the Loading... message was in an iframe that redirected to the file? So you would display the iframe with jQuery, it would have the default message of Loading... and a little spinner animation, then set the iframe's src/location to the ASHX that takes forever to load. You could then give it an onload handler from the iframe's parent page that would hide/remove it. Let me know if you need sample code.

If preparation for the file takes less than default timeout of AJAX request, you may start AJAX request, displaying "Loading..." message to user. AJAX call then checks for file's availability, and when it becomes available - returns with the message (success or not) and gives a link for the file. AJAX request can even do file download, but that's for your option.

Related

Detect when response.redirect has finished?

I have a form that dynamically generates a PDF based on database data. But I don't want to navigate away from the form whilst the PDF is generated and downloaded. So I am using response.redirect to call the .aspx page that generates the PDF and serves it via stream (Have done for many years) so there may be a better option out there now. However I have found people are logging out before the PDF has been sent to the browser which is causing issues.
Is there a way to detect when the reponse.redirect has finished and the file has been downloaded?
I have tried using postmessage and a listener but this doesn't work.
I've also tried setting up and EndRequestHandler as below in my main form:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler) ;
But this hasn't worked either. The browser is aware as as the tab with the main form has a progress icon in, so there must be a way to intercept the complete event.
Might not be accurate like you want it but I do something sort of similar. When the button is clicked, a "Please Wait..." message appear until the file is ready to be downloaded. The way I do it is the client wait for a cookie. When the server is ready to send the file (after processing) it sets a cookie. Even if the cookie was set in a different request, the client still gets the updated value.

Is JavaScript allowed to call a remote web page during a click event?

When viewing the click in firebug, the call turns red (i.e. error) but I can't see the error because the page redirects.
So is it allowed to call a remote website (in my case, its a 1x1 image using a standard url like http://www.example.com/becon).
You are allowed to request images form other domains without issue. Assuming you don't actually care about doing something with the image (ie you're doing data collection with the image request) do something like this:
function getImage(url) {
var tImage = new Image();
tImage.src = url;
}
$('theElementYoureInterestedIn').bind( 'click',
function() {
getImage('http://www.theImage.com/img.jpg')
}
);
Now, if you're looking to get something other than an image (HTML for instance), you'll run into XSS issues.
If I understand your question, yes.
Click events often do AJAX requests (calls to a remote web page) or appending things such as images (which can also have remote web pages).
You can do whatever you want inside the function bound to a click event. Jquery isn't doing anything special there, just binding an event handler.
It sounds like you should place the redirect on hold and inspect the call you're making. Red in firebug means a request returned something other than 200, i.e. a 404 or 500. You might also check your web server's error logs. If you're just sending a request for an image, it sounds like probably it's a 404, and you have the path to the image incorrect.

Unblock (jQuery BlockUI) after file sent to browser through response stream

I have an <asp:button /> that generates a PDF report. I want to use jQuery BlockUI to display a message that says: Generating Report..
Using: Response.BinaryWrite I am then sending the file to the user so it appears as a file download in the browser.
I cannot get $.unblockUI(); to fire. As soon as the file download begins or has completed or is cancelled I want it to dissappear. Currently it never does.. It's as though the page hasn't been re-loaded, I've hit the server but it comes back with the same page.
Things I have tried:
Setting a variable in JS to true so on document.ready() it will call a function if set to true. This doesn't work because even though I change the variable in code it doesn't change the HTML that is sent to the client.
This sort of thing: Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function() { $.unblockUI; }); //register with Microsoft way
$(document).ajaxStop($.unblockUI); //double the insurance and register with jquery way
never gets called..
Can this be achieved with an updatepanel?
Any thoughts?
Also in case it helps:
Response.AddHeader("Content-Disposition", "attachment;filename=""" & ShortFilename & """")
Response.AddHeader("Content-Length", byteArray.Length)
Response.BinaryWrite(byteArray)
Response.Flush()
Response.End()
I can see why this doesn't work sort of, the page is not refreshing in anyway there's just a response stream being sent to the browser, but surely there's an event I can latch on to?
An idea could be to create a child window that does the PDF loading and let the parent figure out when the child window has closed or something.
Is it possible for parent window to notice if child window has been closed?
The solution is to first block the UI as normal. Then make an AJAX request to your report generator, when the PDF is generated store it locally for a short time, or have it in a temporary folder that is cleared out when the user logs out or their login times out. Have the report generator return a success message and a URL.
Have the client ajax request handle the success message, remove BlockUI, then call the URL using:
window.location="http://yourURL/temp/report.pdf
The browser will start to download the file and you are done!
https://stackoverflow.com/a/7660817/181197

Show busy gif after user clicks on a Link

I have a large excel document that is generated when the user clicks on the download link. When the download link is clicked the browser pops up the standard open save cancel dialog. The problem is that the wait time can be really long e.g. 15 seconds or more before the dialog appears. I want to show a busy gif while the request is in progress. How can I accomplish this?
I'm pretty sure I can show a gif easily using jQuery, but I'm not sure how to stop/hide the busy indicator when the new document (excel doc) has finished loading. Is there a javascript event that I could attach a handler to?
Another option is the temporary file method: Is there a way to detect the start of a download in JavaScript?
Basically:
User clicks on download link/button
An AJAX request is sent to create the excel doc. Show the 'busy' indicator.
The excel doc is created and saved to a temporary file on the server. A response is sent containing a unique id that identifies the file.
The AJAX response is handled on the client-side. Hide the 'busy' indicator. window.location is changed to something like 'download.aspx?id=###' which prompts the user to save the file.
The problem here is that clicking the link fires off another request which is nothing to do with the first one. You could have the code that handles the download request update some kind of session data, which a bit of Ajax on the linking page then polls to determine when the request handler is in the process of offering up the data for download.
Alternatively, you could simply make it time out after a reasonable period of time, say 30 seconds, and perhaps offer up an explanation. This might then transition through a couple of states:
"Click here to download the super-duper PDF of awesomeness!"
"Please wait, generating a whole dollop of fonty goodness..."
"It may take some time to bundle all that uber-data into a download...if nothing's happening, maybe you want to try again?"
This seems to be the approach Google Mail takes when it comes to detecting timeouts or similar problems.

ASP.NET 2.0 PageComplete Event troubles and File downloading

I am trying to place an action to happen after an entire .aspx page displays. The "action" is a function that uses the Response object to send a file to the user.
More detailed information:
I am trying to replicate the behavior of a link on the page, from a sidebar. I.E. I have a link on the main page for the Export action, and it works fine -- since the page is already displayed before the user clicks it. But when the user is on a sidebar, clicks the link, it should take them back to this main page and then send the file after it displays.
I did some research and thought that using the PageComplete event would be well-suited for this, so I created my event handler and put the call to the export code (it keys off of a query string when loaded from the sidebar) inside my PageComplete event handler. But it behaves just the same way - the browser download box pops up and the page is never loaded before or after.
If it helps to understand what I'm doing here is a snippet of the code used to send the list to the user.
Response.Clear();
Response.BufferOutput = true;
Response.ContentType = "application/ms-excel";
Response.AppendHeader("content-disposition", "attachment;filename=MyList.xls");
Response.Write(listManager.ExportLists(mycode));
Response.End();
I would prefer a way to use a page event to load the page, rather than tinkering with this logic. But, if there is a clean and easier way to get the file sent, and it allows for loading the page then sending the file, that would be fine too.
Is there another Page event I can use besides PageComplete, or is it possible I am missing something?
EDIT: Sorry about the verbosity. I realize that I can't change the way HTTP requests work - I'm only looking for an acceptable solution that achieves more or less the same results. It seems like the way to go is to force a refresh of the page after a couple of seconds (thus ensuring that it loads before the file download code is executed) -- so I am looking for a way to do this as the first answer suggests - refresh to a download. (It doesn't have to be delayed either, if there's a way to refresh with no waiting)
Why doesn't this code work?
private void Page_LoadComplete(object sender, System.EventArgs e)
{
if (Request.QueryString["action"] != null)
{
if (Request.QueryString["action"] == "export")
{
Response.Redirect("MyHome.aspx?action=exportnow", false);
}
if (Request.QueryString["action"] == "exportnow")
{
ExportMasterList();
}
}
}
What it's supposed to do: after page loading is complete, do a Response.Redirect, reloading itself with a different query string. When it reaches the Page LoadComplete event again, the second time it will trigger the function which writes out the file.
What it actually does: Apparently repeats the same problem twice... it goes back to the same problem, how do you execute an action after the page loads, or wait until the page completely finishes loading, then trigger a refresh which will execute the action? Is there no way for ASP.NET to do something by itself without the user clicking on something?
If that's the case, then an auto-refresh after 2 seconds would also be acceptable... but I'm not sure how to do that.
The server can only return one object to the user, a file download or a page. The best you can manage is to return the user to a page that refreshes to a file download.

Resources