Channels ▼
RSS

.NET

Downloading Large Files: Issues and Tricks


To serve users a server file, you don't need rocket science. A relatively simple piece of code would do the job. You use the OutputStream property of the HttpResponse object to write the bytes you want to send to the client. The following code snippet shows how to save an in-memory graphic document.

Bitmap bmp = new Bitmap(...);
context.Response.ContentType = "image/jpeg";
bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);

Using the OutputStream object directly may be annoying at times. For this reason, the HttpResponse object features a few helper methods. One of these methods is BinaryWrite. As you can see, its implementation is quite straightforward:

public void BinaryWrite(byte[] buffer)
{
    this.OutputStream.Write(buffer, 0, buffer.Length);
}

The method accepts an array of bytes and just writes it out to the stream. What if you want to download an entire file? In theory, you must open the file, read its contents in separate blocks of data and write each block out to the stream. The ASP.NET framework, though, provides us with two specific methods for writing potentially large chunks of data down to the output stream. They are WriteFile and TransmitFile.

The WriteFile method does exactly what you should do yourself to send a file down to the client. It uses an internal file stream to access the content, reads the content in a single shot, and then writes it out to the output stream. In addition, the WriteFile method exposes a simple programming interface where all that you have to do is indicating the name of the file to download. To be precise, WriteFile has a number of overloads and may accept additional parameters, but this doesn't change the basic fact: the method writes out a server file.

Both WriteFile and BinaryWrite methods seem perfect for streaming data down to the client. However, both can put the Web server memory under pressure if called to work on very large files. Why? It's because both methods load the entire data block (the contents of the file or the byte array) into the Web server's memory. For large files, this can cause severe problems that can culminate in the recycling of the ASP.NET process. The TransmitFile method is designed to elegantly work around the problem. It sends output directly from a file to the ASP.NET ISAPI extension and then down to the client, without passing a humongous string to the ISAPI extension.

The TransmitFile method was introduced years ago through a hot-fix package for ASP.NET 1.x as documented in Microsoft KnowledgeBase article KB823409 and later incorporated in the .NET Framework 1.x SP1 and newer versions of ASP.NET. In summary, TransmitFile is the most stable and reliable of the other methods, although you won't notice any significant difference for most files.

Although TransmitFile makes large file downloads more stable than ever and defeats the problem of recycling, it is far from being a full solution to the problem of tracking and resuming large file downloads. For example, if a download fails, for whatever reason, TransmitFile can only start it again from the beginning. In the end, the perfect solution is creating your own file downloader that transmits the file piecemeal, thus avoiding unwanted pressure on the memory and giving the developer the chance of recovering from errors and latency.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.