Uploading large files in .NET you will run into a few issues. There’s
plenty documented other places on the web about this, but in summary IIS
passes the entire file to your asp.NET HttpContext in memory. This
means if someone uploads a 1 gigabyte file…congrats, you now have 1
gig of upload data loaded into ram. This might cause a tiny
scalability problem.
I’ve got to get these specific requirements working:
- Ability to upload files around 1 gig max
- Status bar updated throughout process
- Ajax like page flow which means no going to other page after upload
completes
- No damn viewstate allowed
I’ve got a vendor control at work that fufills the first three, however,
it relies heavily on viewstate, is closed source, expensive, and damn
near imposible to customize the styling. Now it’s throwing random
NullReferenceException errors…so it’s time to upgrade.
There’s a really nice open-source project called Neat
Upload which nicely impements the
pain-in-the-ass code you’ve got to write on the server. Both to provide
support for direct-to-disk streaming (see: no loading into memory) of
the file as well as status updates. It comes packaged with both web
controls (for the weak) and the ability to work straight from an HTML
page with some javascript you’ve got to implement yourself. I found the
client-side html only example to be a bit nasty, and still not exaclty
as easy as it should be. So I looked a bit some more and found this
hot hot script to provide the
client-side goodness allowing for a totally customizable and very
jQuery-esque experience.
Let’s tie the two pieces together, shall we?
The neat upload component will sniff incoming http requests for the post
data with a special key. The key must be in this format:
NeatUpload_##SOMENUMBERHERE##-fileField
The ajax-upload client script allows us to configure the post key
explicitly with it’s “name” configuration variable. Nice. So, we can
set the name variable as follows
//we need to save this postback id when we do a callback for
//the status bar data
var postBackID = Math.round(Math.random() * 100000)+new Date().getTime();
new AjaxUpload('uploadDiv',{
action:'upload.ashx',
name:"NeatUpload_"+postBackID+"-fileField"
});
That is all that’s needed to have the Neat Upload handler pick up on
the upload request.
The action ‘upload.ashx’ page is the handler which will be invoked
after the upload is complete (or if it errors out). You can do
post-processing on the upload afterwards. This is all pretty well
documented in the neat upload examples.
The nice thing about the AjaxUpload library is it will run your upload
request client-side in a separate, hidden iframe. This allows us to
make repeated callbacks to our server to request status from NeatUpload
and when the upload finishes, the page doesn’t redirect anywhere.
Now, we need to set up a few more config parameters on the AjaxUpload
object to be able to call back to the server. Please note I’ve mixed in
a bit of jQuery code below, but it should be easy enough to do this with
your favorite library.
//we'll use this to store the window callback timer
var intervalID;
//we need to save this postback id when we do a callback for
//the status bar data
var postBackID = Math.round(Math.random() * 100000)+new Date().getTime();
new AjaxUpload('uploadDiv',{
action:'upload.ashx',
name:"NeatUpload_"+postBackID+"-fileField",
onSubmit:function(){
intervalID = window.setInterval(function(){
$.getJson('neatupload/progressjsonhandler.ashx?postBackID='+postBackID,
function(data){
//we get a json object back with the current upload status
//we can use the data to update a jquery status bar
//or anything else we see fit
console.log(data.PercentComplete);
});
},1000);//callback interval every second, adjust as you see fit
}
});
Presto. Ajax upload. Nice experience for the client and low load on the server.
Filed under:
Uncategorized by admin