Abstract
Ever try to force the "Download File" dialog in a clients's browser window when you download files that may be supported with a MIME type? Here is an example that works with many versions of IE.
This example illustrates a simple technique to download files of any type from you web application to the client browser. In addition to setting the MIME types, the example shows how to force the Download File dialog that allows the user to either run or save the file, even if the file type would normally display in the browser's window.
On my personal site (http://www.sharkcode.com ), I allow the user to download my resume in various formats including Microsoft Word, HTML, Rich Text and Plain Text. I found that for most users (with IE) the correct application was automatically used to view the document from within their browser (such as Word types like .doc). In all cases, however, I wanted the file to be saved to the client's workstation, rather than simply being displayed by the browser. When I hosted my own site, I could do this by setting the HTTP Headers with "content-disposition" to force the Download File dialog. Now, using the .NET Response object, I can set these headers directly.
The basic ingredients of this example are quite simple and can be found in a Microsoft article at(http://support.microsoft.com/directory/article.asp?ID=KB;EN-US;q306654&lex).
The Microsoft article includes the following code snippet:
private void Page_Load(object sender, System.EventArgs e) { //Set the appropriate ContentType. Response.ContentType = "Application/pdf"; //Get the physical path to the file. string FilePath = MapPath("acrobat.pdf"); //Write the file directly to the HTTP content output stream. Response.WriteFile(FilePath); Response.End(); }
I used this example to write a simple method that accepts a file name as input and a boolean that will force the File Download dialog which allows the client to either run, or save this file to their local workstation.
private void DownloadFile( string fname, bool forceDownload ) { string path = MapPath( fname ); string name = Path.GetFileName( path ); string ext = Path.GetExtension( path ); string type = ""; // set known types based on file extension if ( ext != null ) { switch( ext.ToLower() ) { case ".htm": case ".html": type = "text/HTML"; break; case ".txt": type = "text/plain"; break; case ".doc": case ".rtf": type = "Application/msword"; break; } } if ( forceDownload ) { Response.AppendHeader( "content-disposition", "attachment; filename=" + name ); } if ( type != "" ) Response.ContentType = type; Response.WriteFile( path ); Response.End(); }
The first few lines of code simply convert the file name argument into a physical path (on the server) and get the various component parts of the name. I only handle the file extension of known types that I'm currently using, but this could be extended to support additional MIME types (see the Microsoft article).
If the forceDownload boolean is true, I use the Response.AppendHeader method to add the "content-disposition" which forces the File Download (save) dialog.
I didn't find a lot of online help with the "content-disposition" header. In fact, it may even be on its way out in the future. But this currently works fine with IE 6 (and several prior version of IE upon which I've tested).
I recently found some posts on the ASPAlliance lists that also recommend setting Response.ContentType = "application/x-msdownload" to force the browser's download dialog. This should be especially useful when the type would otherwise be "application/octet-stream". |
Thanks to Mike Harber , I'm able to show the VB.NET version of the C# code example shown above. Thanks Mike.
Private Sub DownloadFile(ByVal fname As String, ByVal forceDownload As Boolean) Dim path As Path Dim fullpath = path.GetFullPath(fname) Dim name = path.GetFileName(fullpath) Dim ext = path.GetExtension(fullpath) Dim type As String = "" If Not IsDBNull(ext) Then ext = LCase(ext) End If Select Case ext Case ".htm", ".html" type = "text/HTML" Case ".txt" type = "text/plain" Case ".doc", ".rtf" type = "Application/msword" Case ".csv", ".xls" type = "Application/x-msexcel" Case Else type = "text/plain" End Select If (forceDownload) Then Response.AppendHeader("content-disposition", _ "attachment; filename=" + name) End If If type <> "" Then Response.ContentType = type End If Response.WriteFile(fullpath) Response.End() End Sub
Send your comments and let me know what you think of this article: [email protected]
Steve Sharrock - www.SharkCode.com and www.AspAlliance.com/shark