Stephen Fischer
Stephen Fischer

Reputation: 2546

Securing Large Downloads Using C# and IIS 7

Here's the setup:

I'm wondering if there is a way to do this using a combination of IIS and C# .Net. All my other servers are running that combo, and it would simplify things a bit if I could do the same for the file servers. The kicker is, the files that are being hosted are large. I've seen examples of people using a small app to create a FileStream object, read in the file, and create the HTTP Response by hand. This works, but since I'm working with files 500+ MB in size, it's slow as heck. And I'll potentially have 300 users hitting the box at once, requesting files. That's no good.

So, anyone see a way around this? I'm trying to create a more transparent system, and if all my servers are running the same software/hardware, it will make my life a whole lot simpler. Thanks in advance for any advice you give!

Upvotes: 9

Views: 1796

Answers (4)

John Gietzen
John Gietzen

Reputation: 49575

You know what? The KB article is poo. Here is my official recommendation:

public void StreamFile(string filePath)
{
    string fileName = Path.GetFileName(filePath);

    using (var fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        var contentLength = fStream.Length;

        if (Request.UserAgent.Contains("MSIE"))
        {
            Response.AddHeader("Content-Transfer-Encoding", "binary");
        }

        Response.ContentType = "application/octet-stream";
        Response.AddHeader("Content-Length", contentLength.ToString());

        // Even though "Content-Disposition" should have an upper-case "d", as per http://www.ietf.org/rfc/rfc2183.txt
        // IE fails to recognize this if the "d" is upper-cased.
        Response.AddHeader("Content-disposition", "attachment; filename=" + fileName);

        var buffer = new byte[8192];

        while (Response.IsClientConnected)
        {
            var count = fStream.Read(buffer, 0, buffer.Length);
            if (count == 0)
            {
                break;
            }

            Response.OutputStream.Write(buffer, 0, count);
            Response.Flush();
        }
    }

    Response.Close();
}

Upvotes: 6

Chris Marisic
Chris Marisic

Reputation: 33128

While this isn't directly applicable since you're using MySql but it's something to consider (might even be available for free by using sql server 2008 express). Sql Server 2008 offers Filestream support which lets you access files as if they are directly stored in the database but actually reside on a fileserver. Then information on the other posts can help you with getting it to the user.

FILESTREAM Storage in SQL Server 2008

Upvotes: 0

Ray
Ray

Reputation: 21905

This thread has my solution to keep memory usage down while users are downloading files. You probably want a bigger buffer than my sample uses, though.

Upvotes: 1

gooch
gooch

Reputation: 575

You may be interested in Microsoft's Background Intelligent Transfer Service (BITS).

http://msdn.microsoft.com/en-us/library/bb968799%28VS.85%29.aspx

Version 2.5 introduced HTTP authentication via certificates.

Upvotes: 0

Related Questions