Login


Creating Downloadable Content Dynamically

By Jonathan Wood on 1/23/2011
Language: C#
Technology: ASP.NETWebForms
Platform: Windows
License: CPOL
Views: 36,279
Web Development » ASP.NET » General » Creating Downloadable Content Dynamically

Screenshot of Demo Project

Download Source Code Download Source Code

Introduction

More and more websites are now getting their content from a database. Pages are generated "on the fly" rather than just being loaded statically from disk.

But there are times when users may want to download content rather than just view it in their browser. For example, they might want data they can load into Microsoft Excel or other applications.

In this article, I'll provide a very simple technique for dynamically generating content that can easily be opened or downloaded as a file.

CSV Files

Much of the database content that is displayed on webpages is displayed in the form of grids. This makes much of that data ideally suited for loading into spreadsheet programs such as Microsoft Excel.

But how can you provide your data in a form that can be loaded into Excel? Excel has a proprietary and complicated file format. The ideal solution won't require you to delve into that. Fortunately, Excel is also able to load CSV files.

Comma-separated-value (CSV) files are plain text files where each value is separated with a comma. Multiple lines are used to define data for multiple rows. This format allows you to easily define data that is arranged in a grid.

Excel can read and save CSV files. If you have Excel installed on your computer, double clicking a CSV file will automatically load that file into Excel (unless you or another program has changed which application is associated with these files).

As mentioned, these are plain text files. However, to work directly with these files, be aware that a few extra steps might be needed. If a value contains a comma or double quotes, the value should be be enclosed within double quotes. And double quotes within the value should be paired to indicate they do not signify the end of the value.

Dynamically Generating a Downloadable File

Okay, sounds easy enough. Using ASP.NET, you can dynamically generate this CSV content from the data in your database. But how do you get the data to download or load into Excel instead of simply being displayed in the browser?

Fortunately, this is very simple to do. You can modify the response headers to indicate you are returning a CSV file attachment instead of "inline" content.

Listing 1 shows my button click event handler that returns the downloadable CSV file. It starts by calling Response.Clear(). Since we are generating a plain text file, we must make certain that no content from the ASP.NET page is included in the response.

Next, we set the Response.ContentType to "text/csv". As you might guess, this tells the browser the type of file being returned. We also add a "content-disposition" header. This tells the browser that we are returning a file attachment that is not to be displayed inline. It also tells the browser the name of the file being returned. The code below gives the file the name "test.csv".

At this point, we use Response.Write() to write the actual data. If this data is coming from a database, this is where you would access the database to produce the content being requested. Be sure you handle the special cases described above if your data might contain embedded commas or double quotes.

Finally, we call Response.End(). Again, this is because we want to return only the plain text we are generating and don't want anything from the current ASP.NET page to be included in the response.

Listing 1: Returning a CSV File as a Downloadable File

protected void btnDownload_Click(object sender, EventArgs e)
{
    // Clear any previous response
    Response.Clear();
            
    // Indicate we're returning a CSV file
    Response.ContentType = "text/csv";
            
    // Provide filename for download
    Response.AddHeader("content-disposition", "attachment;filename=test.csv");
            
    // Write actual CSV data
    for (int i = 0; i < 50; i++)
    {
        Response.Write("Value1, Value2, Value3\r\n");
    }
            
    // Terminate response (prevent additional data)
    Response.End();
}

Conclusion

I've implemented this technique in a very simple way. An alternate way to implement this would be as a separate ASP.NET page. Perhaps you could specify one or more query arguments to indicate what data should be included.

Either way, this is a very simple technique for providing a very useful feature.

End-User License

Use of this article and any related source code or other files is governed by the terms and conditions of The Code Project Open License.

Author Information

Jonathan Wood

I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.