What I have?
I have an 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 do 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 following 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?
Same problem can be replicated in IE6, IE7 and Chrome. I think this problem is browser independent.
I had this same issue with sharepoint. I have a button on the page that sends a file and after clicking the button, the rest of the form was unresponsive. Turns out it is a sharepoint thing that sets the variable _spFormOnSubmitCalled to true to prevent any further submits. When we send a file this doesn't refresh the page so we need to manually set this variable back to false.
On your button in the webpart set the OnClientClick to a function in your javascript for the page.
<asp:Button ID="generateExcel" runat="server" Text="Export Excel"
OnClick="generateExcel_Click" CssClass="rptSubmitButton"
OnClientClick="javascript:setFormSubmitToFalse()" />
Then in the javascript I have this function.
function setFormSubmitToFalse() {
setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
return true;
}
The 3 second pause I found was necessary because otherwise I was setting the variable before sharepoint set it. This way I let sharepoint set it normally then I set it back to false right after.
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();
}
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);
}
// -->
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With