views:

501

answers:

3

What I have?

I have a ASP.NET page which allows the user to download file a on a button click. User can select the file he wants from a list of available files (RadioButtonList) and clicks on download button to download it. (I should not provide link for each file that can be downloaded - this is the requirement).

What I want?

I want the user to download multiple files one by one by selecting the required radio button and clicking on the button.

What problem am I facing?

I can download the file for the first time properly. But, after downloading, if I select some other file and click on the button to download it, click event of the button does not post back and the second file will not be downloaded.

I use the follwoing code on the button click event:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    Response.Clear();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", viewXml.Length.ToString());
    Response.ContentType = "text/plain";
    Response.Write(viewXml);
    Response.End();
}

Am I doing something wrong here?

Thanks in advance!

Update: Same problem can be replicated in IE6, IE7 and Chrome. I think this problem is browser independent.

+1  A: 

Offhand, what you're doing should work. I've successfully done similar in the past, although I used a repeater and LinkButtons.

The only thing I can see that's different is that you're using Response.Write() rather than Response.OutputStream.Write(), and that you're writing text rather than binary, but given the ContentType you specified, it shouldn't be a problem. Additionally, I call Response.ClearHeaders() before sending info, and Response.Flush() afterward (before my call to Response.End()).

If it will help, here's a sanitized version of what works well for me:

// called by click handler after obtaining the correct MyFileInfo class.
private void DownloadFile(MyFileInfo file) 
{
    Response.Clear();
    Response.ClearHeaders();
    Response.ContentType = "application/file";
    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
    Response.AddHeader("Content-Length", file.FileSize.ToString());
    Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
    Response.Flush();
    Response.End();        
}

You may want to consider transferring the file in a binary way, perhaps by calling System.Text.Encoding.ASCII.GetBytes(viewXml); and passing the result of that to Response.OutputStream.Write().

Modifying your code slightly:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    byte [] bytes = System.Text.Encoding.ASCII.GetBytes(viewXml); 
    // NOTE: you should use whatever encoding your XML file is set for.
    // Alternatives:
    // byte [] bytes = System.Text.Encoding.UTF7.GetBytes(viewXml);
    // byte [] bytes = System.Text.Encoding.UTF8.GetBytes(viewXml);

    Response.Clear();
    Response.ClearHeaders();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", bytes.Length.ToString());
    Response.ContentType = "application/file";
    Response.OutputStream.Write(bytes, 0, bytes.Length);
    Response.Flush();
    Response.End();
}
Randolpho
Thanks, Randolpho. No luck with the altered code also. It is behaving the same :(
Vijay
Hmm... well, I'm stumped. Like I said, what I have works fine. Is it possible it's something you do in your code before the click handler is called? If you can, try posting the entire page and code-behind.
Randolpho
+1  A: 

Remove Response.End() and let the response end naturally within the ASP.NET ecosystem.

If that does not work, I would recommend putting the button in a separate <form> and post the required data to a separate HTTP handler. Setup the HTTP handler to export the XML instead of a web page.

Josh Stodola
Initially I had not included `Response.End()`. It was not working then as well!
Vijay
Hmmm. Well, maybe you can try putting the button in a separate `<form>` and post the required data to a separate HTTP handler that is setup to export the XML?
Josh Stodola
Also, you should specify a content encoding like `Response.ContentEncoding = Encoding.UTF8`
Josh Stodola
Josh, thanks for the suggestion. I could achieve the task using HTTP Handler. Can you please put that as an answer so that I can mark it?
Vijay
@Vijay Answer updated.
Josh Stodola
A: 

A simple way to do this without removing Response.End is to add client-side js to do the page refresh. Add the js to your button's onclientclick property.

e.g.

    onclientclick="timedRefresh(2000)"

then in your html..

    <script type="text/JavaScript">
    <!--
    function timedRefresh(timeoutPeriod) {
        setTimeout("location.reload(true);",timeoutPeriod);
    }
    //   -->

Digitz