I'm trying to make a file upload handler in C# that is asynchronous and can provide updates on progress of the file through AJAX asynchronous requests. Basically if the request is a POST it loads some information into the session and then starts the upload, if the request was a GET it returns the current state of the upload (bytes uploaded, total bytes, etc). I'm not entire sure that it needs to be an asynchronous handler but the files could be quite large so I thought that would work best. For the base async handler I used something very similar to the handler in this MSDN article. I've posted below some key sections of my code below. The issue I'm having is that I don't receive any of the GET information back until the POST has completed. I will mention that in this example I am using jQuery for GET requests and BlueImp for posting the file.
The HTML and JavaScript
<input id="somefile" type="file" />
$(function () {
name = 'MyUniqueId130';
var int = null;
$('#somefile').fileupload({
url: '/fileupload.axd?key='+name,
done: function (e, data) { clearInterval(int); }
});
$('#somefile').ajaxStart(function(){
int = setInterval(function(){
$.ajax({
url: '/fileupload.axd?key='+name,
dataType: 'json',
async: true
})
.done(function(e1, data1){
if(!e1.InProgress || e1.Complete || e1.Canceled)
clearInterval(int);
});
}, 10000)});
});
The Asynchronous Process Request Method just calls the correct method whether it's a POST or GET to one of the following then calls CompleteRequest to end the request:
private static void GetFilesStatuses(HttpContext context)
{
string key = context.Request.QueryString["key"];
//A dictionary of <string, UploadStatus> in the session
var Statuses = GetSessionStore(context);
UploadStatus ups;
if (!String.IsNullOrWhiteSpace(key))
{
if (Statuses.TryGetValue(key, out ups))
{
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.Write(CreateJson(ups));
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
}
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.Write(CreateJson(Statuses.Values));
}
}
private static void UploadFile(HttpContext context)
{
var Statuses = GetSessionStore(context);
string key = context.Request.QueryString["key"];
if (String.IsNullOrWhiteSpace(key))
{
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
return;
}
HttpPostedFile file = context.Request.Files[0];
string extn = file.FileName.LastIndexOf('.') == -1 ? "" :
file.FileName.Substring(file.FileName.LastIndexOf('.'), (file.FileName.Length - file.FileName.LastIndexOf('.')));
string temp = GetTempFileName(path, extn);
UploadStatus status = new UploadStatus()
{
FileName = file.FileName,
TempFileName = temp,
Path = path,
Complete = false,
Canceled = false,
InProgress = false,
Success = true,
BytesLoaded = 0,
TotalBytes = file.ContentLength
};
Statuses.Add(key, status);
byte[] buffer = new byte[bufferSize];
int byteCount = 0;
using (var fStream = System.IO.File.OpenWrite(context.Request.MapPath(path + temp)))
{
uploads.Add(status);
while ((byteCount = file.InputStream.Read(buffer, 0, bufferSize)) > 0 && !status.Canceled)
{
status.InProgress = true;
status.BytesLoaded += byteCount;
fStream.Write(buffer, 0, byteCount);
}
status.Complete = !status.Canceled;
status.InProgress = false;
status.Success = true;
if (status.Canceled)
{
Statuses.Remove(temp);
}
context.Response.StatusCode = (int)HttpStatusCode.OK;
}
}
I've tried many things such as non-async handlers, async handlers, making sure the JavaScript is runnning async, but at this point I think I need some different eyes on the problem so thank you for any assistance anyone can provide.