Jeff and .NET

The .NET musings of Jeff Putz

Sponsors

News

My Sites

Archives

HttpHandlers and big files

I use an HttpHandler on my podcast site to catch the requests for MP3's and increment a download counter. This seems to work pretty well, and I haven't had any problems to date. It also helps force the "save as" dialog so people aren't viewing them in their browsers.

However, when I try to apply the same concept to big video files, it chokes. iTunes says the network connection is reset while Firefox simply says the document contains no data.

What might be going on here? The code is what you've likely seen in countless examples elsewhere, like this:

public class MovHandler : IHttpHandler
{
    public MovHandler()
    {
    }
   
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.Clear();
        context.Response.ContentType = "video/quicktime";
        string path = context.Server.MapPath(context.Request.FilePath);
        NewsItem item = new NewsItem(Path.GetFileName(context.Request.FilePath));
        item.Downloads++;
        item.Update();
        context.Response.WriteFile(path);
        context.Response.End();
    }
}

Posted: Nov 01 2005, 05:35 PM by Jeff | with 9 comment(s)
Filed under:

Comments

Josh Christie said:

Jeff,
I believe you need to write the file out manually a chunk of bytes at a time in a loop if the file is greater than 2GB. Make sure you turn response buffering off. Also, you should be using TransmitFile instead of WriteFile since it performs much better.

Josh
# November 1, 2005 6:01 PM

DmitryR said:

How big is the file?

Another alternative is to use Response.TransmitFile() - it would not read the bits into memory. But it is also limited to 2GB.

Also, no need to call Response.End.

Thanks,

Dmitry
# November 1, 2005 6:22 PM

Jeff said:

By "large," I meant under 100 MB still.
# November 1, 2005 6:43 PM

Mital Kakaiya [MCSD.NET] said:

I am just wondering how do I know file has been downloaded completely, to maintain a real counter "item.Downloads++;"

User can click on "cancel" button during the download process, which should not increase a counter value.

# November 1, 2005 9:10 PM

Jeff said:

Well, you don't know, and honestly, I don't care enough to know for sure. :)

Switching to TransmitFile() solved the problem. That was easy. I'm still curious about the actual implementation of each method, however.
# November 1, 2005 10:23 PM

Frans Bouma said:

I had the same problem, but with memory consumption: WriteFile loads the file completely in memory before streaming it to the client.

So I switched to TransmitFile to do a test. No memory hogging anymore, but what's weird: the files are sometimes just 64KB, not 11MB. Also, TransmitFile isn't documented in the MSDN. Pretty obscure though...
# November 2, 2005 4:12 AM

Guy Murphy said:

Could this not be better done as a filtering module that simply observed the file fetch and made note of it, rather than a handler that dealt with serving the file? The handler is not actually adding any service value, and so might be redundant... a module should allow you to make the observations you need.
# November 2, 2005 4:33 AM

Josh Christie said:

Jeff,
TransmitFile uses a kernel-mode API to stream the file directly onto the network (it's what IIS uses internally) while WriteFile does all sorts of user-mode copying around between buffers before the file ends up on the network.

Josh
# November 2, 2005 9:13 AM

Fizzy Pish » HttpHandlers and streaming files said:

PingBack from http://fizzypish.wordpress.com/2006/06/16/httphandlers-and-streaming-files/
# June 17, 2006 3:24 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)