Download file via handler without ending current response - asp.net

On my page I have a button to download a document.
I am building the page with steps, so step 1 is choosing a type, step 2 is downloading the document and step 3 is to write some information in a textbox.
What I would like to do is to show step 3 after the button for the download has been pressed.
So in the button_click event I first put some code to show step 3 and then I need to do something to download the form.
To download the document I use a ASHX handler file. That works fine.
But my problem is that when I go to that handler, my page is not updated.
I used
response.redirect("GiveFile.ashx?file=document.doc",false)
After some reading I found that using response.redirect ends the current response so the page is not updated.
I was thinking of creating a new response and redirect that one to the handler file, but I can't find an example to see how that is done. I also don't know if it will work.
I also tried
server.transferrequest("GiveFile.ashx?file=document.doc",true)
but that also ends the current response.
Who can help me with this?
rg,
Eric

Google is using a hidden iframe to download files 'in the background'.
Check this article with code sample:
http://encosia.com/ajax-file-downloads-and-iframes/

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.

disable a direct access to a specific web page in ASP.NET

Is there a trusted way to disable the direct access to an special web page? I mean I want to open it only by clicking on a Button for example. I know I can access to the webpage by using this code but It can not prevent accessing to the web page directly (Pasting the url or typing it):
Response.Redirect("~/Code.aspx")
Thanks
This is a long shot because I don't have the time to test this now (I can see some downvotes coming already!), but...
In the "Code.aspx" page, check for Session["allowed"]. If the value is not there, end the response.
Next, make another page (from where Code.aspx can be accessed). In this page, set Session["allowed"] and then do a Server.Transfer() to Code.aspx, which will then run OK.
Finally, at the end of processing Code.aspx., remember to clear the Session["allowed"] variable again.
Hope this makes even vague sense :)
You may be able to write a piece of code on page load that checks the contents of HttpContext.Current.Request.ServerVariables("HTTP_REFERER") - if it's blank, a user has navigated to the page directly and you can handle it that way.
On the source page create a token into a hiddenfield. To your button add PostBackUrl property and let it point to your destination page.
On the destination page you can validate that the request was made from your allowed source page. And you dont need to use session and all its drawback.
Check this Link for detailed information about how to use the mentioned property.

ASP.NET log requests to Amazon S3 objects

I've put some objects in an S3 bucket and I want to log everytime a client makes a request to one of those objects.
I'm using Umbraco 4.8 as my back-end with some custom code running.
The solutions I've come up with:
Set the link to an ASP page that pulls the object from S3 and sends it back as the response. The problem I see there is then the client has to wait for ASP to load the file before it can begin downloading the file.
Set the link to an ASP page that logs the request and returns a Response.Redirect to the S3 object. To me this seems like an unnecessary redirect and the client might cache that redirect and not hit my server the next time they access that object.
Does anyone have any other solutions or thoughts on how to achieve this? Any help would be appreciated.
I would use jquery and google analytics. Add a class to each link that you want to track and then use jquery to manipulate the onclick event to something like:
link text
Replacing the three variables appropriately ('s3-Bucket-Request', 's3-actual-bucket-name', 'current-page'). If you then put the jquery at the head of each page you have a reusable function.
start:
link text
jquery:
$('.ga').attr("onclick", "__gaq.push(['_trackEvent', 's3-Bucket-Request', 's3-actual-bucket-name', 'current-page']);");
end:
link text
Depending on how accurate you need this to be, you could also do it client side. Using jQuery, etc, add a click handler to a href tags that makes an ajax request to a controller, logging the activity.

Redirecting to a slow aspx page

I have a performance issue where we have a 2 page setup as part of a workflow in a bigger system. This section is dedicated to rendering reports allowing users to chose their own parameters.
Page1.aspx collects parameter information for a report. It takes the information submitted on a form and validates it. If it validates OK, it stores the selections in the DB as XML, then redirects to Page2.aspx with the run id in the query string. Simple enough, performance is great.
Page2.aspx pulls the ID out of the DB and hydrates a Crystal ReportDocument object (taking milliseconds) then we call ExportToHttpStream which then renders the report as a PDF or DOC or XLS download (output format is determined in Page1.aspx). The performance of the ExportToHttpStream method is very poor due to the way our reports are written and DB indexes on the target system. This is outwith my control at the moment but I am promised that they are being worked on.
So the problem is, that when the submit button in Page1.aspx is pressed, the user experiences a very long delay before the download starts. It is then compounded by the user pressing the submit button again thinking there is a problem.
I think what I need to do is have Page1.aspx redirect to Page2.aspx. Page2.aspx should render the master page furniture and a loading div, and the report should render asynchronously somehow in the background before the save dialogue automatically pops up, after this i'd like to change the loading div to a 'Report generated, click here to go back'.
If this is the best way to achieve this, how can I load a full page, then request the report asynchronously? I'm open to any suggestions here.
You could use ajax to load the report on Page2.aspx and show a loading message while it's processing.
Look at the jQuery.load() method. This might be the easiest way to accomplish what you are trying to do.
Page1.aspx - collect parameters
Page2.aspx - report view, calls Page2Details.aspx via ajax.
Try loading Page2.aspx inside iframe and use jQuery to display waiting indicator and hide it after Page2.aspx download
Whilst both answers gave me some ground to go out and research in the right direction. My solution included using the fileDownload plugin from John Culviner to facilitate a similar solution:
jQuery fileDownload by John Culviner
This allowed me the following page structure:
Page1.aspx, gathers and validates parameters for the report and puts them into Oracle.
Page2.aspx, whilst passed in the runid (pointer to the parameters in the db) via the query string setup 3 hidden divs. Loading, Error and Success.
The script mentioned above was employed at this point. jQuery firstly sets the loading div visible then calls the plugin. The plugin dynamically creates an iframe and downloads the binary (xls/doc/pdf) from Page3.aspx. It then fires a success callback or failure. The success callback is fired by means of a cookie set at the end of the response in Page3.aspx.
I believe the plugin mentioned downloads using a 'text/plain' AJAX call in jQuery avoiding the limitation of there not being an octet-stream equivalent in AJAX.
It works, its not the cleanest solution by any means, it doesn't degrade one bit, but provides the users on our controlled intranet with an extremely responsive and pleasing UI.

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.

Resources