views:

430

answers:

4

I have a page in my vb.net web application that needs to toss a bunch of data into a text file and then present it to the user for download. What's the best / most efficient way to build such a text file on a .net web server?

Edit: to answer a question down below, this is going to be a download once and then throw-away kind of file.

Update: I glued together the suggestions by John Rudy and DavidK, and it worked perfectly. Thanks, all!

+4  A: 

Use a StringBuilder to create the text of the file, and then send it to the user using Content-Disposition.

Example found here: http://www.eggheadcafe.com/community/aspnet/17/76432/use-the-contentdispositi.aspx

private void Button1_Click(object sender, System.EventArgs e)
{
        StringBuilder output = new StringBuilder;
        //populate output with the string content
        String fileName = "textfile.txt";

        Response.ContentType = "application/octet-stream";
        Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
        Response.WriteFile(output.ToString());

}
Should definitely specify an encoding, preferable UTF-8
Vincent McNabb
+4  A: 

Don't build it at all, use an HttpHandler and serve the text file direct into the output stream:

http://digitalcolony.com/labels/HttpHandler.aspx

The code block halfway down is a good example, you can adjust to your own:

public void ProcessRequest(HttpContext context)
{
   response = context.Response;
   response.ContentType = "text/xml";       
   using (TextWriter textWriter = new StreamWriter(response.OutputStream, System.Text.Encoding.UTF8))
   {
       XmlTextWriter writer = new XmlTextWriter(textWriter);
       writer.Formatting = Formatting.Indented;
       writer.WriteStartDocument();
       writer.WriteStartElement("urlset");
       writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
       writer.WriteAttributeString("xsi:schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd");
       writer.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");

       // Add Home Page
       writer.WriteStartElement("url");
       writer.WriteElementString("loc", "http://example.com");
       writer.WriteElementString("changefreq", "daily");
       writer.WriteEndElement(); // url

       // Add code Loop here for page nodes
       /*
       {
           writer.WriteStartElement("url");
           writer.WriteElementString("loc", url);
           writer.WriteElementString("changefreq", "monthly");
           writer.WriteEndElement(); // url
       }
       */
       writer.WriteEndElement(); // urlset
   }                      
}
Meff
A: 

Bear in mind it doesn't ever need to be a 'file' at the server end. It's the client which turns it into a file.

Will Dean
+3  A: 

The answer will depend on whether, as Forgotten Semicolon mentions, you need repeated downloads or once-and-done throwaways.

Either way, the key will be to set the content-type of the output to ensure that a download window is displayed. The problem with straight text output is that the browser will attempt to display the data in its own window.

The core way to set the content type would be something similar to the following, assuming that text is the output string and filename is the default name you want the file to be saved (locally) as.

HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.ContentType = "application/octet-stream";
response.Charset = "";
response.AddHeader("Content-Disposition", String.Format("attachment; filename=\"{0}\"", filename));
response.Flush();
response.Write(text);
response.End();

This will prompt a download for the user.

Now it gets trickier if you need to literally save the file on your web server -- but not terribly so. There you'd want to write out the text to your text file using the classes in System.IO. Ensure that the path you write to is writable by the Network Service, IUSR_MachineName and ASPNET Windows users. Otherwise, same deal -- use content type and headers to ensure download.

I'd recommend not literally saving the file unless you need to -- and even then, the technique of doing so directly on the server may not be the right idea. (EG, what if you need access control for downloading said file? Now you'd have to do that outside your app root, which may or may not even be possible depending on your hosting environment.)

So without knowing whether you're in a one-off or file-must-really-save mode, and without knowing security implications (which you'll probably need to work out yourself if you really need server-side saves), that's about the best I can give you.

John Rudy