I am creating a file dynamically in my web application. I want to send this file to the user, just like many sites do when you download a file.
I first tried the approach at Download/Stream file from URL - asp.net. But that didn't work because I'm in a class that's a layer removed from the ASPX web page; my result was that the file overwrote itself, alternating with I was unable to create the proper Request/Response objects.
Then I tried this approach:
try
{
    WebClient myClient = new WebClient();
    string basefile = Path.GetFileName( file_name );
    myClient.DownloadFile( file_name, basefile );
}
    catch (WebException we)
{
        string message = we.Message;
}
This raised an exception: Access to the path 'C:\Program Files (x86)\IIS Express\file-being-sent.ext' is denied.
So, how do I stream the file?
ETA my previous attempt:
    //Create a WebRequest to get the file
    HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create( url ); //Send request to this URL
    //Create a response for this request
    HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
    //if (fileReq.ContentLength > 0)
    //    fileResp.ContentLength = fileReq.ContentLength;
    //Get the Stream returned from the response
    //stream = new Stream();
    writer = new StreamWriter( file_name );
    //stream = writer.BaseStream.Length
    // prepare the response to the client. resp is the client Response
    var resp = HttpContext.Current.Response;
    //Indicate the type of data being sent
    //resp.ContentType = "application/octet-stream";
    resp.ContentType = "application/zip";
    //Name the file 
    resp.AddHeader( "Content-Disposition", "attachment; filename=\"" + Path.GetFileName( file_name ) + "\"" );
    resp.AddHeader( "Content-Length", writer.BaseStream.Length.ToString() );
    // Verify that the client is connected.
    if (resp.IsClientConnected)
    {
        resp.Write( writer );
        resp.Flush();
    }
I haven't figured out what to pass to the call to HttpCreateRequest().
ETA2: Here's what I'm presently using. Various SOF posts say this should prompt the user with an Open Or Save dialog, but it still does not do so for me.
StreamReader reader = new StreamReader( file_name );
var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
resp.ContentType = "application/zip";
resp.AppendHeader( "Content-Disposition", "attachment; filename=\"" + Path.GetFileName( file_name ) + "\"" );
resp.AppendHeader( "Content-Length", reader.BaseStream.Length.ToString() );
// Verify that the client is connected.
if (resp.IsClientConnected)
{
    resp.Clear();
    resp.TransmitFile( file_name ); //does not buffer into memory, therefore scales better for large files and heavy usage
    resp.Flush();
}
ETA3:  The IIS trace log reports an exception, System.Web.HttpException: Server cannot set content type after HTTP headers have been sent.  This does not make sense to me, as I'm setting the content type before appending headers.
Stack trace is:
[HttpException (0x80004005): Server cannot set content type after HTTP headers have been sent.]
System.Web.HttpResponse.set_ContentType(String value) +9681570
System.Web.HttpResponseInternalWrapper.set_ContentType(String value) +41
System.Web.UI.PageRequestManager.RenderPageCallback(HtmlTextWriter writer, Control pageControl) +139
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +268
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
System.Web.UI.Page.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +57
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1386
ETA4:  I moved the streaming into the ASPX page's code-behind file, which has direct access to the Response object.  I'm still getting the same exception.  I'm at a loss to explain why the generally accepted approach is complaining to me that a response has already been sent, or otherwise why my code won't prompt the user to download the file.