Refresh Web Pages After Download Completed

By Vasanthakumar D

I would like to address one common issue here and one way solving the issue....

In webpages, you are using the below code to donwload some files...

        Response.ContentType = "application/vnd.ms-word";
        string slFilename = "NewBusiness.doc";
        Response.AddHeader("content-disposition", "attachment; filename=" + slFilename + "");
        string AllContent = ViewState["Cont"].ToString();
        Response.Write(AllContent);
        Response.End();








As you are using Response.End, this will render the page again. So, the changes done before download the file wont reflect in the browser.
this is the normal behaiour of the browsers...

you can overcome this issue using client side page reload using Javascript or anyother scripting languages. Lets take the below example..




<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript" language="javascript">
    var isReload = false;
    function DownloadFiles()
    {
        if(isReload == true)
        {
            isReload = false;
            window.location.reload();     
        }
        else
        {
            isReload = true;
        }
        window.setTimeout("DownloadFiles()", 2000);
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label runat="server" ID="lblMsg"></asp:Label>
        <asp:Button ID="Button1" runat="server" Text="Download" OnClientClick="DownloadFiles();" OnClick="Button1_Click"/>
    </div>
    </form>
</body>
</html>



you can able to see that I am calling a Javascript function DownloadFiles() which reload the page after 2 seconds of the download button is clicked.   The main problem here is, suppose the page take 5 seconds to download the file?....In that case, after 2 seonds the page will be reloaded. So, you wont get the download.

you may increase the setTimeout's duration by 10000 or even 60000. This leads to a problem, suppose your download finished within 2 seconds. So, the page will reload after 10 seconds or 1 minute. And also, you cannot vary the setTimeout interval dynamically, due to dynamice operations before download the file......

So, how can we overcome this ?...................

here is my approach to solve this issue.....

for this, you need to split the download operations into two parts.

1. Geneartion Download File Content and accomplish pre-download operations (Download button)
2. Download the original file from previouly genrated content. (hidden button)

for you need to have a download button along with a hidden button.

Pre-download things will be handled by Download button and download opeartion will be handled by hidden button

here is the Sample HTML for this




 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript" language="javascript">
    var isReload = false;
    function DownloadFiles()
    {
      document.getElementById("btnHidden").click();
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label runat="server" ID="lblMsg"></asp:Label>
        <asp:Button ID="btnDownload" runat="server" Text="Download" OnClick="btnDownload_Click"/>
        <asp:Button ID="btnHidden" runat="server" Text="Download" OnClick="btnHidden_Click" style="display:none;"/>
    </div>
    </form>
</body>
</html>


you can see that, there two button named as btnDownload and btnHidden. btnDownload is used for pre-download operations and btnHidden is used to download the file.

Lets consider a scenario, I have a list files in database and allow the users to download the files. So, in web page I will a grid wtih filename and download button in each row. Once use downloaded the file from the page, we need to remove the donwloaded file from download list.

for this sceanrio, in pre-download we need to change the selected flag of the file as downloaded in database and store the content of file in session or view-state.

And in download operation, we can retrive the file content from session or view-state and we can download nomrally.

here is the code for this

Pre-Download

protected void btnDownload_Click(object sender, EventArgs e)
    {
        string AllContent = "test";
        ViewState["Cont"] = AllContent;
        lblMsg.Text = "Completed";
        Page.ClientScript.RegisterStartupScript(this.GetType(), "rel", "DownloadFiles();", true);
    }

you can see that, I am saving the file content in view state, and change the message label lblMsg's content to 'Completed'. So, our download button will work normally and render the page.
And  register startup script inovke the DonwlodFiles() Js, which inturn invoke the hidden button's server side click event as
   function DownloadFiles()
    {
      document.getElementById("btnHidden").click();
    }


and in hidden button server click event, you can retrive the file content from view state and write it into to Response for download.

protected void btnHidden_Click(object sender, EventArgs e)
    {
        Response.ContentType = "application/vnd.ms-word";
        string slFilename = "NewBusiness.doc";
        Response.AddHeader("content-disposition", "attachment; filename=" + slFilename + "");
        string AllContent = ViewState["Cont"].ToString();
        Response.Write(AllContent);
        Response.End();
    }


I hope this article will be helpful to overcome this issue..........
Popularity  (8596 Views)
Create New Account
Article Discussion: Refresh Web pages after download completed...
Vasanthakumar D posted at Monday, June 15, 2009 6:32 AM
reply
Roger replied to Vasanthakumar D at Wednesday, June 17, 2009 7:59 AM
This article was VERY useful - thanks for the insight.
reply
sahil replied to Roger at Wednesday, June 17, 2009 7:59 AM
You are Rocking. It solve my problem.

Regards

Sahil Kaundal( Mohali)
reply
Keith replied to Vasanthakumar D at Wednesday, June 17, 2009 7:59 AM

We're using almost exactly this solution on our project, but it creates an interesting issue sometimes.

 

First the context...

In our case we have download and view links - view opens in a new page, and download opens the file as an attachment for immediate download. 

In both cases we need to update the page to reflect the changes in the files download history.  We're doing this with an ajax update of the relevant divs.

 

Now the problem...

When ie8 (and other versions of ie I suspect) attempts to download the file, the hiding of the actual download event in script can cause issues with the pop-up blocker mechanisms.

I've seen the blocker come up repeatedly, and not be able to be allowed, or come up once and then all downloads from then on.  All this despite the fact that no pop-up is being used.

 

Finally, a possible (but ugly) solution...

Our solution is to prepare the download and update the page (as though the download had occured) in the on-click, and then make the actual link in the Anchor tag into the final file link.  This means that on clicking the link, the server is notified of the pending file request, updates its records, and passes back the ajax response for the page changes.  The client then updates the page according to the ajax response, and finally returns true from the onClick event, allowing the link to be followed.  When the link is followed it is a normal file download and should avoid issues around pop-up blockers etc.

While this (should) avoid the pop-up issues, it could mean the page getting updated as if the download had occured, when in fact it failed before or during the actual download event.  This might be best handled by having the download mark the download as successful in later call.

 

In the end I end up with something like this... (in semi-pseudocode)

 

<A onclick='return preclick(this,FILEID);' href='/files/download/filename.pdf?fileId=FILEID' ajaxtarget="ajaxdivid">download</A>

 

function preclick(source,fileid){

   // Update the download status for the file getting a "Download pending" state

   Ajax_update(source.ajaxtarget,fileid);

 

   // set an event to occur in 3 secs to re-update the download status for the file detting a "Downloaded" state  

   setTimeout(Ajax_update(source.ajaxtarget,fileid),3000);

   return true;

}

 

I'm still not entirely satisfied with this solution (I wish there was an afterFollowLink event available for <A> tags.) but hopefully someone may find it useful.

reply
Raj Reddy replied to Vasanthakumar D at Wednesday, June 17, 2009 7:59 AM
Very Very Txs i struggled a lot to find solution for this. I thought i will not find sol. for this. Allast u provided the sol. Txs a lot
reply
Raj Reddy replied to Raj Reddy at Wednesday, June 17, 2009 7:59 AM

i used the same code to refresh the page after the download complete by using Response.Write.

 

But 1 issue is there with this code. i.e. Images are not rendering in the page.

 

My Problem is : I have gridview in my page. In this i have a clumn having a dropdown control. Based on selection of the dropdown item grid data will change by hitting the databse. And also export link is there to export this data to the Excel.

 

issue is : Clicking on Export i used the same code to export and after to refresh the page. But images are not coming present in the page

reply
Nikola replied to Vasanthakumar D at Wednesday, June 17, 2009 7:59 AM

Hi All,

 

I would just add a little change on the solution with dividing of the creation of the file from download process.

On the page, add  hidden button and in the click event put the download code.

On the click event of the User download button put the code for the creation of the file and set programmatically Javascript funtion which will occure on the page onload Javascript event. In this function put hte Javascript code for causing the click event of the Download button. Also, in the Session object remember the path to the file which is created in the User download button. This path value will be read in the download event. In this way, problem of, how many seconds to set for refreshing the page does not exists, because Your page is showing every change You want before download process start.

reply
sam samy replied to Nikola at Wednesday, June 17, 2009 7:59 AM
Just to add one thing more to the referred solution :

ADDITION  : To track exactly when download task is over instead of measuring it download time duration  

SCENARIO : I am showing a div containing the download information and then hiding it after the download is over by using "document.readyState  " property.

NOTE : First time when we are calling this check() function then the readyState  property will show complete so have handled it with a variable check and then the value will be "loading" till the download is complete.

JAVA SCRIPT :
<script type="text/javascript" >
    var isReload = false;
    function check() {
    
        var divid = document.getElementById("BlockDiv");
        if (isReload == true) {
            isReload = false;
            if (document.readyState == "complete")
                divid.style.visibility = "hidden";
            else
                window.setTimeout("check()", 100);
        }
        else {
            divid.style.visibility = "visible";
            isReload = true;
            window.setTimeout("check()", 100);
        }</script>









reply
sam samy replied to sam samy at Wednesday, June 17, 2009 7:59 AM
Sorry it was not a  reply to the above users solution as it shows "replied to Nikola"
but just a general way of tracking download which may be useful in some scenarios
reply