Downloading Files - Forcing the File Download Dialog
By Steve Sharrock
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".
|
Visual Basic Example
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:
steve@sharkcode.com
Steve Sharrock - www.SharkCode.com and
www.AspAlliance.com/shark
|