Tuesday, August 23, 2005

HtmlInputFile problem uploading large files!

God I have spent nearly 4 days solid trying to work that one out!

Here is the challenge:
Basically there is by a size limit to the file you can upload to a webserver using the good old HtmlInputFile Input. By default this limit is 4Mb and it is set in the machine.config file on the web server:

httpruntime maxrequestlength="8192"

It is of course possible to override this value in your web.config file and make it web app specific.

The problem occurs when you try to upload something bigger than that... you will get a nasty DNS error because the asp.net worker process got its knickers in a twist on the webserver. It basically reached a memory threshold before it could do anything with the file!

A full explanation can be found here:
http://support.microsoft.com/default.aspx?scid=kb;en-us;295626

Anyway the bottom line is that it displays a nasty error to the user and the people I work for don't like that at all.

As a Google group lover I looked for an answer to that one for a lot longer than I originally thought I would have to and finally found this EXCELLENT article by Jesse Chunn:
http://www.standardio.org/article.aspx?id=213

Jesse you're the man! The little code snippet you posted is awesome in simplicity and it works great.

The trick is to use the global.asax file and to test the file contentLength for every single request made to the web server.

I post the code again:

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)

' Fires at the beginning of each request
Dim i As Integer

'this number is in bytes, NOT kilobytes!!
Dim iMaxFileSize As Integer = 8000000
For i = 0 To Request.Files.Count - 1
If Request.Files.Item(i).ContentLength > iMaxFileSize Then
Response.Redirect("FileToBig.aspx?filesize=" & Request.Files.Item(i).ContentLength)
Exit For
End If
Next

End Sub

A massive thank you to you my friend, you're a star in the developer's world!!!

11 comments:

Jesse Chunn said...

Etienne,
I'm glad you found the article so useful. After the trouble I had with the issue, I figured there were lots of folks out there that would appreciate a solution.
Jesse Chunn

Anonymous said...

Good stuff. Thanks. Here's the C# version for anyone who's interested. Note that I've put the Request total length check before the individual file check (enumerating the files when the request total content length exceeds the maximum will result in an HttpException)


///------------------------

/// Fires at the beginning of each request
protected void Application_BeginRequest(object source, EventArgs e)
{

#region Check for submission where Total Length / File Length Greater than allowed

// this number is in bytes, NOT kilobytes!!
int maxFileSizeKBytes = 1024; // 1MB
int maxRequestSizeKBytes = 4096; // 4MB

/// Validate request against request size threshold
if(Request.ContentLength > (maxRequestSizeKBytes * 1024))
{
Response.Redirect("RequestToBig.aspx?requestSize=" + Request.ContentLength.ToString());
}

/// Validate each file against file size threshold
for(int i = 0; i < Request.Files.Count; i++)
{
if(Request.Files[i].ContentLength > (maxFileSizeKBytes * 1024))
{
Response.Redirect("FileToBig.aspx?fileSize=" + Request.Files[i].ContentLength.ToString());
}
}

#endregion
}

Anonymous said...

this doesn't work on some machines like mine. The response.redirect doesn't fire

Anonymous said...

this code is not working.if you upload the file with size limit more than specified,then REquest.Files line is getting break.So Please any one could help me.Its very urgent.

Unknown said...

Hi and thanks for your comments, for the developers who have not been able to get this to work you must make sure that the machine.config (or web.config of your site) has its maxrequestlength bigger than anything you are testing for in your Application_BeginRequest Sub. If you are still having problems feel free to leave your details and I will try to help you as much as I can ;o)

Many thanks!

CBK Prasad said...

Hi Etienne,

I have tried the posted code in ASP.NET 2.0;Its not working. My HttpMaxRequestLength in web.config is set to 40000KB and I have tested with nearly 650MB File. If you can help me in this regard it would be greatful for me. If you can send me the reply on my mail id cbkprasad@gmail.com it will be very helpfull for me.

Thanks in advance..
Prasad

Unknown said...

ASPNET 2.0 UPDATE. just add <httpRuntime maxRequestLength="8192" /> in the <system.web> of your web.config to increase the upload size limit. 8192 is 8MB

Anonymous said...

You could also use an applet able to split file in chunks before upload.
That's way, no matter of upload size limits.

See: http://www.jfileupload.com/products/jfileupload/index.html

Unknown said...

For us the Response.Redirect doesn't seem to work. When I look in the server log I see the HTTP code 302 response but the next request to the server is then invalid (it seems empty) and returns a status code 400. So I decided to look with fiddler to see if the returned response seems valid, and strange enough it works ok when I have fiddler open. Now we can't ask clients to open fiddler before connecting ...

Anonymous said...

I have exactly the same issue. I was under the impression Fiddler doesn't modify the requests/responses but with Fiddler running the browser does receive the "maximum request length exceeded" (even without the code example, since it's already being checked in my web.config), without Fiddler IE7 returns an error after 5 minutes.

Imho setting the web.config maximum very large as the only way to get a "nice" error to the browser is a horrible solution and can lead to DDOS attacks.

Anonymous said...

Has anyone figured out why this works with fiddler open? I'm having the same problem.