The question of providing a file trough a SaveAs dialog in a web browser appears very often in the forums and QA websites like Stackoverflow.

The default action of the web browser when a file is provided is to open it.
It automatically determines the file type and opens it inside the browser. An example would be a link to a .pdf, an excel or image file etc. When you click on it it opens the file in another tab or another page.

You have two options to achieve this depending whether you are using an already existing file or you are dynamically generating it(or getting it from a database or such).

The first alternative is to use HttpResponse.TransmitFile method to send the file to a response. Which will display the SaveAs dialog asking you for a location where to store
the file. First you need to set the ContentType property and add the Content-Disposition and/or Content-Length headers for the response.

Here’s an example:

string filePath = "~/path/SomeExcelFile.xlsx";
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", filePath));
Response.AddHeader("Content-Lenght", fileInfo.Length.ToString());
Response.ContentType = "application/ms-excel";

This will cause a SaveAs dialog to appear with the SomeExcelFile.xlsx as the default filename.

The transmit file approach is valid only if you are providing an existing file. If for example you are generating a file dynamically or reading it from a database you can use the
property to write directly to the output stream. For example:

Bitmap bmp = new Bitmap(10, 10);
Response.ContentType = "image/jpeg";
Response.AppendHeader("Content-Disposition", "attachment; filename=bitmap.jpg");

bmp.Save(Response.OutputStream, ImageFormat.Jpeg);

There is also another approach using Response.BinaryWrite:

using (DataContext db = new DataContext())
    var objData = (from c in db.Companies where c.CompanyId == CompanyID select c.LogoSmall).FirstOrDefault();
    using (System.IO.MemoryStream stream = new System.IO.MemoryStream(objData.ToArray(), true))
        stream.Write(objData.ToArray(), 0, objData.ToArray().Length);
        Byte[] bytes = stream.ToArray();
        Response.ContentType = "image/jpeg";
        Response.AppendHeader("Content-Disposition", "attachment; filename=image1.jpg");

This will read the binary data from the database using Linq-to-Sql and will provide the file for saving appearing a SaveAs dialog with theimage1.jpg as the default filename.

Adding the Response.End() can be ommited, but you may inadvertently be sending other content back after Response.BinaryWrite() which may confuse the browser. Response.End() will ensure that that the browser only gets what you really intend.

Hope this helps to someone out there.

‘Till next time….Taaa daaaa.



Posted by TheBoyan

I have been programming since I was 11 years old (Yes, I'm one of those, for real). First programming language I learned was BASIC, on a Commodore64. Then around high-school it was C and Assembly. Just before and during university days it was C++. I started doing some professional work during this period, part of the reason why I dropped out of uni in my final year. I have never stopped since then. Going through a plethora of technologies ranging from C and Assembly languages, Delphi to C++, C#, Java and so on and so forth... trough 20 (and more, who counts, does it even matter) years of software development. I have not lost even a single bit of my ambition and love for the craft from those first young days, nor the energy...I absolutely love what I do. I like to get my hands into all aspects of software development. Now-a-days I use mainly Microsoft related technologies .NET C#, with a lot of database design/management usage of SQL server, but not in any way limited to that.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s