ASP.NET File Upload with *Real-Time* Progress Bar - redux

So, guess who just got the memo ...

 

Dear Matt,

Uploading large files with ASP.NET is difficult.

 

Sincerely,

Every ASP.NET Developer and their Mother

 

After sufficiently embarrassing myself with my earlier post, I decided it was high time I spend a little bit more time understanding this problem.  And lo and behold Jon Galloway has already written up a nice survey on the topic.  So to bone up on the issues I followed all of the links Jon provided as well the ones provided by all of the one-off emails I received in response to my previous post (thanks everyone).

Of all the upload components I checked-out (SWFUpload, FileUp, Flajaxian FileUploader, RadUpload, NeatUpload, ASP.Net File Upload/Download Module, etc...) I was the most interested in the last 2 (NeatUpload and ASP.Net File Upload/Download Module).  They are both free, have my kind of licensing and come with the full source code.

So I downloaded both of these components and played around with plugging them into the demo app I blogged about previously.  Both components include progress bar web controls, but I already have a progress bar widget that I really like.  So my focus was on seeing what it would take to leverage only the HttpModule portion of these components and checking out how I could have the module interface with my progress bar.  Like I mentioned previously, I want something that looks like this ...

image

image

image

 

NeatUpload Vs. Darren Johnstone's ASP.Net File Upload/Download Module

Both NeatUpload and Darren Johnstone's components seem to have a rather large following, but I chose to see how I could extend Darren's control because it was already using AJAX plus a custom HttpHandler to communication the upload progress back to the client.  And that seems really close to what I wanted.  If this doesn't pan out, NeatUpload actually seems to have a larger following so I will probably go back and revisit this topic using NeatUpload instead.

 

How it Works

From what I can tell, Darren's component basically works by injecting a hidden INPUT element into the form that contains the file INPUT(s).  The value of the hidden element is a Guid that contains a well-known prefix (Darren uses the token ::DJ_UPLOAD_ID::).  Then as his custom HttpModule is processing the request, it looks to see if the form contains this token.  If so, he tucks the upload progress information into memory using the id value as the index.  Then, if a client wants to query the upload progress, they can query his component using this guid as the look-up value. 

Below is a screen capture of the request body.  The hidden field is highlighted in yellow.       

image  

 

Querying the Upload Status

The second cool thing about Darren's control is that he has included a custom handler for accessing the progress of an upload.  This makes is pretty simple to get at the upload progress using your favorite AJAX library.  Below is a small snippet of JavaScript that I am using in my demo app for getting at the status of the current upload.   

   1: intervalID = window.setInterval(function(){
   2:  
   3:     var request = new Sys.Net.WebRequest();
   4:     request.set_url('UploadProgress.ashx?DJUploadStatus=' + token + '&ts=' + new Date().getTime());
   5:     request.set_httpVerb('GET');                
   6:     request.add_completed(function(executor){
   7:     
   8:         //  the progress is returned as xml
   9:         var e = executor.get_xml().documentElement;                   
  10:         var empty = e.getAttribute('empty');
  11:     
  12:         if(!empty){
  13:         
  14:             //  extract the attributes I am interested in
  15:             var percent = e.getAttribute('progress');
  16:             var file = e.getAttribute('file');
  17:             var kbs = Math.round(parseInt(e.getAttribute('bytes')) / 1024);    
  18:             var size = Math.round(parseInt(e.getAttribute('size')) / 1024);                        
  19:         
  20:             //  update the progressbar to the new value
  21:             progressBar.set_percentage(percent);
  22:             //  upadte the message
  23:             updateMessage('info', 'Uploading ' + file + ' ... ' + kbs + ' of ' + size + ' KB');
  24:             
  25:             if(percent == 100){
  26:                 //  clear the interval
  27:                 window.clearInterval(intervalID);                        
  28:             }                        
  29:        }                    
  30:     });  
  31:     
  32:     //  invoke the request
  33:     request.invoke();
  34:     
  35: }, 1000);

 

Sample App

No live demo this time, but I do have a sample application.  You can download it here.

 

Conclusion

Well, that's about it.  I am curious, how have you handled file uploads in the web apps you have worked on?  3rd party component?  Something home-grown?  One of the components I mentioned above?

 

That's it.  Enjoy!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/142

Listed below are links to weblogs that reference ASP.NET File Upload with *Real-Time* Progress Bar - redux:

» Progressbar Bookmarks from Post Saver - Website voting and saving system
Bookmarked your page with keywords progressbar! [Read More]

Comments


Posted by: NMyVision on July 31, 2008 07:50 PM

I've used Flash Upload specifically the flex version, for a couple projects. I added a little bit more functionality to read an external xml file to set max size constraints (15MB), file type (pdf,doc) and (images) and lastly added some javascript logic to do postbacks on complete or cancel.

We use the Telerik file upload control....

I hate it.. with a passion.

Posted by: Jonx on August 1, 2008 10:19 AM

Cool, a new post has arrived :)

I'm using SWFUpload. That made me discover that flash is not crossplatform neither is it crossbrowser when it comes to authentified sessions. Can you believe that flash is sending the IE cookies when it runs in FF or opera. So funny ;)
Anyway. I needed SWFUpload because I needed to multiselect more the one file at a time. I find that SWFUpload and Flash upload have too much flash, especially the latest.

So here is the chalenge...
I would like an upload solution that uses essentially HTML/JAvaScrip and lets me select more then one file at a time. As the multi selet is only possible in Flash I would love to see someone extract that small piece of code from SWFUpload for example and use it in a standard ASP.NET/HTML/Javascript solution :) Does his exist somewhere ? Any takers?

I find that uploading a single file has very litle use except in a contact page for example...

Nonetheless, your sample is slick and simple to use. Thanks.

I also use the Flash Upload. I like it's ability to queue, track, and upload multiple files and the design freedom it provides. I'm not sure about it's filesize limitations though.

I made a rudimentary .NET control with it and blogged about it a while back (http://weblogs.asp.net/jstengel/archive/2008/04/25/flash-file-upload-server-control.aspx)

I don't usually have to deal with large files but I did a little test with the biggest file I could quickly locate on my system (a 431mb VS SP2 update). It seemed to upload that okay.

I do like what you've come up with as well. Thanks for sharing.

Posted by: Jonx on August 3, 2008 11:05 AM

Also note that you have a 4 series articles on asp.net about that subject:
http://www.misfitgeek.com/AJAXstyle+File+Uploader+With+Progress+Indicator+And+Uploaded+Files+List.aspx

Posted by: Pwrjng on August 5, 2008 09:12 AM

Hi,Matt
I am just wondering where can i download this HTTP log viewer? Could you give me the link please?
Thanks.

Posted by: Steve on August 5, 2008 10:56 PM

I think obout.com has a nice one as well.

http://www.obout.com/fup/


@Jonx -
Joe's examples don't show real-time progress though - right?

@Pwrjng -
Certainly - its called WebDevHelper and its a great tool. Here is the link: http://projects.nikhilk.net/WebDevHelper/

Posted by: michael on August 8, 2008 01:14 PM

We use MediaChase's FileUploader.NET http://www.mediachase.com/fuploader/overview.aspx

It has a few quirks but doesn't force you to use any particular interface or other fluff. This has advantages and disadvantages - you can write your own AJAXy stuff around it but you have to write your own AJAXy progress stuff.

Posted by: Hussain on August 12, 2008 09:57 PM

Really great application but how to I set the directory where the file would be uploaded?

Posted by: Hussain on August 13, 2008 01:17 PM

Matt,

How can I set the directory/path where I want the file to be upload?

Great article... one question I have is how would this be done using a Multiple file upload type control?

Lee, you could do something like this in your Global.asax:

void Processor_Init(object sender, FileProcessorInitEventArgs args)
{
if (args.Processor is FileSystemProcessor)
{
FileProcessor processor = args.Processor as FileProcessor;

// Set up the download path here
processor.OutputPath = @"C:\downloads";
}
}

Posted by: Hussain on August 24, 2008 04:26 PM

I have set the download path in the Global.asx.cs in the Processor_Init subroutine but I cannot seem to get the application to upload it to that directory. Right now the application keeps uploading to the webroot directory. Below is the syntax that I have used to set the download directory.

processor.OutputPath = @"C:\temp";

Regardless of the directory path in the above line, the file gets saved to the webroot directory.

Any ideas as so why this is happening?

Is is possible to make this work with a FTP server?

Tan

Hussain, What I did was to move the file using File.Move as follows:

File.Move(HttpContext.Current.Server.MapPath("~/" + fileName),HttpContext.Current.Server.MapPath("~/uploads/" + fileName));

this uses the System.IO namespace.

I placed this code in Uploads.aspx in the page load event.

Matt, thanks for this upload tool, much appreciated.

Posted by: chris on September 11, 2008 07:47 AM

Hi

If i try to use this upload Solution in my Project i get the assembly error: Assembly manifest doesn't match assembly reference.
How can i use my AjaxControlToolkit Version with this Upload Solution ??

Posted by: Srinivas on September 15, 2008 04:20 PM

Hi,

I was trying to use the fileupload component, but it gives me the error "Microsoft JScript runtime error: 'progressBar' is null or not an object".

I would appreciate if you can guide me to fix this issue.

Thanks
Srinivas

Posted by: Keith on September 17, 2008 08:46 AM

When I run the sample code I'm unable to use the settings in Global.asax. I'm trying to get the code to save the files somewhere else on the network, but it's still using the default location in spite of my making the suggested changes. Any insight into what I might be doing incorrectly?

Posted by: Umesh Singh on September 20, 2008 09:07 AM

Hi, Matt

Please always mention ASP.NET Framework Version, if the any post is related to ASP.NET......

Posted by: David on October 1, 2008 01:47 PM

Hi,

Great control! Any idea why it doesn't work if tracing is enabled?

-David

Posted by: Srinivas on October 9, 2008 10:44 AM

Matt,
Thanks for the great fileupload control!!

I was using this tool in my application to upload large size media files (size between 100mb to 500mb). I was wondering is there any way we can pass the file name as a parameter to this tool so that i acn assign unique file name for each upload.

we are using .Net framework 3.5
Any help will be appreciated.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Srinivas wrote: Matt, Thanks for the great fileupload control!! I was using this tool in my application to upload l...
  • David wrote: Hi, Great control! Any idea why it doesn't work if tracing is enabled? -David ...
  • Umesh Singh wrote: Hi, Matt Please always mention ASP.NET Framework Version, if the any post is related to ASP.NET.......
  • Keith wrote: When I run the sample code I'm unable to use the settings in Global.asax. I'm trying to get the cod...
  • Srinivas wrote: Hi, I was trying to use the fileupload component, but it gives me the error "Microsoft JScript runt...
  • chris wrote: Hi If i try to use this upload Solution in my Project i get the assembly error: Assembly manifest ...
  • Mike wrote: Hussain, What I did was to move the file using File.Move as follows: File.Move(HttpContext.Current....
  • Vitrification wrote: Is is possible to make this work with a FTP server? Tan...