If my download page is like this;
<asp:Button ID="btnDownload" runat="server" Text="Download" OnClick="btnDownload_Click" />
code-behind
protected void btnDownload_Click(object sender, EventArgs e)
{
string path = "~/files/pic.png";
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", String.Format("attachment;filename={0}", Path.GetFileName(path)));
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(File.ReadAllBytes(Server.MapPath(path)));
Response.Flush();
Response.End();
}
So clicking the download button causes the code to write the files/pic.png file to the client and it triggers a download in the browser. If I look at the request in Fiddler it is to this url
http://localhost:50725/Default.aspx
and the post data is like this;
__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=D2GscibKx2pwUA ...
That's the form values on the page. The important bit of post data is the bit that tells asp.net that the download button has been clicked, that's this
ctl00%24MainContent%24btnDownload=Download
If I view the source of my page I see my download button is called "ctl00$MainContent$btnDownload" (it's using master pages ergo the weird name). So I want to POST to that url with that in the post data and that will make asp.net think the request has come from a browser clicking the download button, so I just grab the response and save it to a file;
string url = "http://localhost:50725/Default.aspx";
NameValueCollection data = new NameValueCollection();
data.Add("ctl00$MainContent$btnDownload", "Download");
using (WebClient client = new WebClient())
{
byte[] result = client.UploadValues(url, data);
File.WriteAllBytes(@"c:\temp\download.png", result);
}
I'm using a png file but it doesn't matter what the file is, this will work for Excel files, EXE files, any binary data.