Upload Large Files in ASP.NET Using HttpModule

 AS you may know, ASP.NET by default only allows the maximum request length to be 4MB. The developer needs to modify the web.config file to allow the upload process to handle large files.
If you use Reflactor and you dissamble the HttpRequest under System.Web, you will find a method called GetEntireRawContent which will check if the request is larger than the value in the web.config and throws an error

                if (length > maxRequestLengthBytes)
                {
                    throw new HttpException(SR.GetString("Max_request_length_exceeded"), null, 0xbbc);
                }


In this article, Haissam Abdul Malak will demonstrate how to upload large files in ASP.NET without the need to modify the value of maxRequestLength attribute of the httpRuntime tag in the web.config.

We will create an HttpModule which will read the file in chunks (500KB per chunk).
We will handle the BeginRequest event and use the HttpWorkerRequest which provides more low level control for the request.
Below is the full implementation of the HttpModule. I included comments to enable you to fully understand each line of code.

I recommend connecting to msdn and read about HttpWorkerRequest class. Personally i didnt know about the existence of such class except lately.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace HAMModule
{
    public class MyModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            app.BeginRequest += new EventHandler(app_BeginRequest);
           
        }
        void app_BeginRequest(object sender, EventArgs e)
        {
            HttpContext context = ((HttpApplication)sender).Context;

            if (context.Request.ContentLength > 4096000)
            {
                IServiceProvider provider = (IServiceProvider)context;
                HttpWorkerRequest wr = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
                FileStream fs = null;
                // Check if body contains data
                if (wr.HasEntityBody())
                {
                    // get the total body length
                    int requestLength = wr.GetTotalEntityBodyLength();
                    // Get the initial bytes loaded
                    int initialBytes = wr.GetPreloadedEntityBody().Length;
         
                    if (!wr.IsEntireEntityBodyIsPreloaded())
                    {
                        byte[] buffer = new byte[512000];
                        string[] fileName = context.Request.QueryString["fileName"].Split(new char[] { '\\' });
                        fs = new FileStream(context.Server.MapPath("~/Uploads/" + fileName[fileName.Length-1]), FileMode.CreateNew);
                        // Set the received bytes to initial bytes before start reading
                        int receivedBytes = initialBytes;
                        while (requestLength - receivedBytes >= initialBytes)
                        {
                            // Read another set of bytes
                            initialBytes = wr.ReadEntityBody(buffer, buffer.Length);
                            // Write the chunks to the physical file
                            fs.Write(buffer, 0, buffer.Length);
                            // Update the received bytes
                            receivedBytes += initialBytes;
                        }
                        initialBytes = wr.ReadEntityBody(buffer, requestLength - receivedBytes);
                       
                    }
                }
                 fs.Flush();
                 fs.Close();
                 context.Response.Redirect("UploadFinished.aspx");
            }

        }
        public void Dispose()
        {
        }
    }
}


To know the file name selected by the user, I had to use javascript function on the page containing the fileupload control to change the action property of the form tag to post to the same page with a query

string parameter containing the selected file name. Users will be redirected to a page called "UploadFinished.aspx" to display a successful upload process message.

Below is the javascript function

 <script language="javascript">
        function SetAction()
        {
                   document.form1.action = 'default.aspx?fileName=' + document.getElementById('FileUpload1').value;
        }
    </script>
And call it using
<asp:FileUpload ID="FileUpload1" runat="server" onpropertychange="SetAction()" />
You need to register the module in the application web.config file by placing the below inside the <system.web> tag.

<httpModules>
        <add type="HAMModule.MyModule" name="MyModule"/>
</httpModules>

Hope this helps,

 

Published 12 September 2008 10:01 AM by haissam

Comments

# amrelgarhy said on 05 October, 2008 03:29 PM

Please can you tell me how to organize files in a web project, and put which code in which file as i wrote everything you did but it didn't work at all with me and one more thing:

i didn't find an event for FileUpload control  called "onpropertychange" there is one called "onchange".

Thanks,

# icianedwards said on 03 July, 2009 04:57 AM

Absolute Genius!!!

# Alok Arora said on 13 August, 2009 02:50 AM

I tried this module but getting NullReference error on line

nt initialBytes = wr.GetPreloadedEntityBody().Length;

# Maven said on 02 September, 2009 12:40 AM

Same Problem: Getting NULLreference at following line:

int initialBytes = wr.GetPreloadedEntityBody().Length;

# Anshul said on 04 September, 2009 04:43 PM

if you are using internet explorer then it show NULLreference . I dont know why ...but code runs fine in firefox

# yashera said on 05 September, 2009 07:39 AM

Hi haissam,

i am yasher araabath, i am new to this blog.. , first of all i just want to thank u for providing this much support. its very helpful for people like me.. i am having only 1.5yrs exp in dot net..i could't understand properly the module which u post..

i just want to upload files above 20Mb..

i tried the coding, but its gives an ""Object null reference"" error msg in the line---""int initialBytes = wr.GetPreloadedEntityBody().Length;"".

where to place(mean Which form) the coding of MyModule...i just add one class file named that class file to MyModule and place the coding u written..and getting the error i mentioned above...

please help me to solve this problem....waiting for ur reply...

Once again thank u for ur support....

# codatic said on 11 September, 2009 08:08 PM

To fix the null reference use this:

int initialBytes = wr.GetPreloadedEntityBodyLength();

# Rohan said on 26 November, 2009 06:27 AM

Hi,

Thanks for the lovely code,

When I created a demo from the code given, the Uploaded file had some extra information at the start and the end of the file.

Thats why the file was shown as 'corrupted' while opening it. The extra data seem to be some _viewstate data and some asp.net control data.

eg...

-----------------------------7d9277710e16

Content-Disposition: form-data; name="__VIEWSTATE"

/wEPDwUKMTI3MTMxMTcxN2RkeP5Qd/t+09T/ZfZ5ACzD1u6aiYw=  ......

Is there anyway to remove it...

Thanks and regards,

Rohan !!!

# How to Upload 100MB file? - Programmers Goodies said on 29 September, 2011 03:06 AM

Pingback from  How to Upload 100MB file? - Programmers Goodies

# Blog de l'équipe support IIS France -- French IIS Support Team Blog said on 19 June, 2013 12:05 PM

I've recently worked on a very interesting file upload issue where my customer was hitting a 2 GB upload

# Uploading large file to IIS 7.5 or 8 using file input element » Short CodeX said on 19 June, 2013 03:19 PM

Pingback from  Uploading large file to IIS 7.5 or 8 using file input element » Short CodeX

# Uploading large file to IIS 7.5 or 8 using file input element | MSDN Blogs said on 19 June, 2013 04:59 PM

Pingback from  Uploading large file to IIS 7.5 or 8 using file input element | MSDN Blogs

This site

Search

Go

This Blog

Syndication

Sponsors

  • MaximumASP