Friday, May 27, 2011

ASP.NET server side handler for Valums Ajax file upload ; file uploader supports multiple file upload with progress bar , drag-and-drop

This ajax uploader uses XHR for uploading multiple files with progress-bar in FF3.6+, Safari4+, Chrome and falls back to hidden iframe based upload in other browsers, providing good user experience everywhere. You can also see php demo in Valums site http://valums.com/ajax-upload/
The current implementation has server side handler for java, php and Perl. But does not exist Asp.net handler. Here I have implemented a Asp.net handler for ajax file upload that supports  IE, Firefox and Chrome.
Problem is IE use context.Request.Files[] for sending file to server. But Firefox and Chrome use Context.Request.InputStream. So in handler you need to check both for reading stream.
For Firefox and Chrome you get fileName from header like
String filename = HttpContext.Current.Request.Headers["X-File-Name"];
Code that work in Firefox and Chrome
//This work for Firefox and Chrome.
Stream inputStream = HttpContext.Current.Request.InputStream;
FileStream fileStream = new FileStream(mapPath + "\\" + filename, FileMode.OpenOrCreate);
inputStream.CopyTo(fileStream);
fileStream.Close();
context.Response.Write("{success:true, name:\"" + filename + "\", path:\"" + path + "/" + filename + "\"}");
But for IE you need to use
HttpPostedFile uploadedfile = context.Request.Files[0];
Code that work for IE browser :
HttpPostedFile uploadedfile = context.Request.Files[0];
filename = uploadedfile.FileName;
uploadedfile.SaveAs(mapPath + "\\" + filename);
context.Response.Write("{success:true, name:\"" + filename + "\", path:\"" + path + "/" + filename + "\"}");
Here the response is send as JSON string and you will get JSON object as response. you need to send {success:true} to make ajax upload understand that file upload is successful otherwise you can send false.

Complete code is:
public void ProcessRequest(HttpContext context)
      {
          const string path = "Capture/Images";
          String filename = HttpContext.Current.Request.Headers["X-File-Name"];
          if (string.IsNullOrEmpty(filename) && HttpContext.Current.Request.Files.Count <= 0)
          {
              context.Response.Write("{success:false}");
          }
          else
          {
              string mapPath = HttpContext.Current.Server.MapPath(path);
              if (Directory.Exists(mapPath) == false)
              {
                  Directory.CreateDirectory(mapPath);
              }
              if (filename == null)
              {
                  //This work for IE
                  try
                  {
                      HttpPostedFile uploadedfile = context.Request.Files[0];
                      filename = uploadedfile.FileName;
                      uploadedfile.SaveAs(mapPath + "\\" + filename);
                      context.Response.Write("{success:true, name:\"" + filename + "\", path:\"" + path + "/" + filename + "\"}");
                  }
                  catch (Exception)
                  {
                      context.Response.Write("{success:false}");
                  }
              }
              else
              {
                  //This work for Firefox and Chrome.
                  FileStream fileStream = new FileStream(mapPath + "\\" + filename, FileMode.OpenOrCreate);
                  try
                  {
                      Stream inputStream = HttpContext.Current.Request.InputStream;
                      inputStream.CopyTo(fileStream);
                      context.Response.Write("{success:true, name:\"" + filename + "\", path:\"" + path + "/" + filename + "\"}");
                  }
                  catch (Exception)
                  {
                      context.Response.Write("{success:false}");
                  }
                  finally
                  {
                      fileStream.Close();
                  }
              }
          }
      }

Complete solution is available in codeproject http://www.codeproject.com/KB/aspnet/AspNetHandlerAjaxUpload.aspx

4 comments:

  1. hi! first, thank you for your snippet.

    when i use your snippet (if upload file is large) Failed error returns and upload process cancels.

    how can i learn why i get error. how can i response to screen this error description in "FileUpload.ashx".

    i would like to upload large file over 2GB.

    thank you very much for your help.

    ReplyDelete
  2. I have debugged on fileupload and get that
    HTTP Error 404.13 - Not Found
    \n The request filtering module is configured to deny a request that exceeds the request content length.

    The solution is you need to set maximum content length in web.conf or IIS in request filter

    add following lines in IIS for 2GB
    I have debugged on fileupload and get that
    HTTP Error 404.13 - Not Found
    \n The request filtering module is configured to deny a request that exceeds the request content length.

    The solution is you need to set maximum content length in web.conf or IIS in request filter

    add following lines in IIS for 2GB
    <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime executionTimeout="24000" maxRequestLength="4124672" />

    </system.web>

    <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <security>
    <requestFiltering>
    <requestLimits maxAllowedContentLength="4223664128" />
    </requestFiltering>
    </security>
    </system.webServer>

    ReplyDelete
  3. How can i send extra data with file ?

    ReplyDelete
  4. Hi.
    Thank you for your post.
    A line of code is vague for me.
    Can I ask you please explain it?

    String filename = HttpContext.Current.Request.Headers["X-File-Name"];

    What does this line of code?

    ReplyDelete