JavaScript/jQuery FileUploader - Server-Side Implementation in ASP.NET

Depending on whether the FileUploader sends Ajax requests or uses an HTML form to upload files, the server must be configured differently. Ready-to-use implementations for both these cases are given below.

See Also

Ajax Upload

C#
VB
[HttpPost]
// "file" is the value of the FileUploader's "name" property
public ActionResult AsyncUpload(HttpPostedFileBase file)
{
    // Specifies the target location for the uploaded files
    string targetLocation = Server.MapPath("~/Files/");

    // Specifies the maximum size allowed for the uploaded files (700 kb)
    int maxFileSize = 1024 * 700;

    // Checks whether or not the request contains a file and if this file is empty or not
    if (file == null || file.ContentLength <= 0) {
        throw new HttpException("File is not specified");
    }

    // Checks that the file size does not exceed the allowed size
    if (file.ContentLength > maxFileSize) {
        throw new HttpException("File is too big");
    }

    // Checks that the file is an image
    if (!file.ContentType.Contains("image")) {
        throw new HttpException("Invalid file type");
    }

    try {
        string path = System.IO.Path.Combine(targetLocation, file.FileName);
        // Here, make sure that the file will be saved to the required directory.
        // Also, ensure that the client has not uploaded files with malicious content.
        // If all checks are passed, save the file.
            file.SaveAs(path);
    }
    catch (Exception e) {
        throw new HttpException("Invalid file name");
    }
    return new EmptyResult();
}
<HttpPost>
Function AsyncUpload(file As HttpPostedFileBase) As ActionResult
    ' Specifies the target location for the uploaded files'
    Dim targetLocation As String = Server.MapPath("~/Files/")

    ' Specifies the maximum size allowed for the uploaded files (700 kb)'
    Dim maxFileSize As Integer = 1024 * 700

    ' Checks whether or not the request contains a file and if this file is empty or not'
    If (IsNothing(file) Or file.ContentLength <= 0) Then
        Throw New HttpException("File is not specified")
    End If

    ' Checks that the file size does not exceed the allowed size'
    If (file.ContentLength > maxFileSize) Then
        Throw New HttpException("File is too big")
    End If

    ' Checks that the file is an image'
    If (Not file.ContentType.Contains("image")) Then
        Throw New HttpException("Invalid file type")
    End If

    Try
        Dim path As String = System.IO.Path.Combine(targetLocation, file.FileName)
        ' Here, make sure that the file will be saved to the required directory.'
        ' Also, ensure that the client has not uploaded files with malicious content.'
        ' If all checks are passed, save the file.'
            file.SaveAs(path)
    Catch ex As Exception
        Throw New HttpException("Invalid file name")
    End Try

    Return New EmptyResult()

End Function

You can pass the exception messages to the client using a custom action filter:

C#
VB
[NonAction]
protected override void OnActionExecuted(ActionExecutedContext filter) {
    var exception = filter.Exception;
    if (exception != null) {
        filter.HttpContext.Response.StatusCode = 500;
        filter.Result = new JsonResult {
            Data = exception.Message
        };
        filter.ExceptionHandled = true;
    }
}
<NonAction()>
Protected Overrides Sub OnActionExecuted(ByVal filter As ActionExecutedContext)
    Dim exception As Exception = filter.Exception
    If exception IsNot Nothing Then
        filter.HttpContext.Response.StatusCode = 500
        filter.Result = New JsonResult With {.Data = exception.Message}
        filter.ExceptionHandled = True
    End If
End Sub
See Also

HTML Form Upload

C#
VB

public ActionResult SyncUpload() {

    // Specifies the target location for the uploaded files
    string targetLocation = Server.MapPath("~/Files/");

    // Specifies the maximum size allowed for the uploaded files (700 kb)
    int maxFileSize = 1024 * 700;

    // Checks whether the request contains any files
    if(Request.Files.Count == 0)
        return View("Index");

    HttpFileCollectionBase files = Request.Files;
    for (int index = 0; index < files.Count; index++ ) {
        HttpPostedFileBase file = files[index];

        // Checks that the file is not empty
        if (file.ContentLength <= 0)
            continue;
        string fileName = file.FileName;

        // Checks that the file size does not exceed the allowed size
        if (file.ContentLength > maxFileSize)
            continue;

        // Checks that the file is an image
        if (!file.ContentType.Contains("image"))
            continue;

        try {
            string path = System.IO.Path.Combine(targetLocation, file.FileName);
            // Here, make sure that the file will be saved to the required directory.
            // Also, ensure that the client has not uploaded files with malicious content.
            // If all checks are passed, save the file.
                file.SaveAs(path);
        }
        catch (Exception e) {
            continue;
        }
    }
    return View("Index");
}

Function SyncUpload() As ActionResult
    ' Specifies the target location for the uploaded files'
    Dim targetLocation As String = Server.MapPath("~/Files/")

    ' Specifies the maximum size allowed for the uploaded files (700 kb)'
    Dim maxFileSize As Integer = 1024 * 700

    Dim files As HttpFileCollectionBase = Request.Files

    ' Checks whether the request contains any files'
    If files.Count = 0 Then
        Return View("Index")
    End If

    For i = 0 To files.Count - 1
        Dim file As HttpPostedFileBase = files(i)

        ' Checks that the file is not empty'
        If (file.ContentLength <= 0) Then
            Continue For
        End If

        Dim fileName As String = file.FileName

        ' Checks that the file size does not exceed the allowed size'
        If (file.ContentLength > maxFileSize) Then
            Continue For
        End If

        ' Checks that the file is an image'
        If (Not file.ContentType.Contains("image")) Then
            Continue For
        End If

        Try
            Dim path As String = System.IO.Path.Combine(targetLocation, file.FileName)
            ' Here, make sure that the file will be saved to the required directory.'
            ' Also, ensure that the client has not uploaded files with malicious content.'
            ' If all checks are passed, save the file.'
                file.SaveAs(path)
        Catch ex As Exception
            Continue For
        End Try
    Next i

    Return View("Index")
End Function
See Also

Chunk Upload

View Demo

C#
VB
// The structure that represents chunk details
public class ChunkMetadata
{
    public int Index { get; set; }
    public int TotalCount { get; set; }
    public int FileSize { get; set; }
    public string FileName { get; set; }
    public string FileType { get; set; }
    public string FileGuid { get; set; }
}
[HttpPost]
// "file" is the value of the FileUploader's "name" property
public ActionResult ChunkUpload(HttpPostedFileBase file, string chunkMetadata)
{
    // Specifies the location for temporary files
    string tempFileLocation = Server.MapPath("~/Files/Temp/");
    // Specifies the target location for uploaded files
    var targetLocation = Server.MapPath("~/Files/");

    try {
        if (!string.IsNullOrEmpty(chunkMetadata))
        {
            // Gets chunk details
            ChunkMetadata metaDataObject = JsonConvert.DeserializeObject<ChunkMetadata>(chunkMetadata);

            // ...
            // Perform security checks here
            // ...

            // Creates a directory for temporary files if it does not exist
            if (!Directory.Exists(tempFileLocation))
                Directory.CreateDirectory(tempFileLocation);

            var tempFilePath = Path.Combine(tempFileLocation, metaDataObject.FileGuid + ".tmp");

            // Appends the chunk to the file
            AppendContentToFile(tempFilePath, file);

            // Saves the file if all chunks are received
            if (metaDataObject.Index == (metaDataObject.TotalCount - 1))
                System.IO.File.Copy(tempFilePath, Path.Combine(targetLocation, metaDataObject.FileName));
        }
    }
    catch {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    return new EmptyResult();
}

void CheckMaxSize(FileStream stream)
{
    if (stream.Length > 1024*400000)
        throw new Exception("File is too large");
}

void AppendContentToFile(string path, HttpPostedFileBase content)
{
    using (FileStream stream = new FileStream(path, FileMode.Append, FileAccess.Write))
    {
        content.InputStream.CopyTo(stream);
        CheckMaxSize(stream);
    }
}
' The structure that represents chunk details
Public Class ChunkMetadata
    Public Property Index As Integer
    Public Property TotalCount As Integer
    Public Property FileSize As Integer
    Public Property FileName As String
    Public Property FileType As String
    Public Property FileGuid As String
End Class
<HttpPost>
Function ChunkUpload(file As HttpPostedFileBase, chunkMetadata As String) As ActionResult
    ' Specifies the location for temporary files
    Dim tempFileLocation As String = Server.MapPath("~/Files/Temp")

    ' Specifies the target location for uploaded files
    Dim targetLocation = Server.MapPath("~/Files/")

    Try
        If (Not String.IsNullOrEmpty(chunkMetadata)) Then
            ' Gets chunk details
            Dim metaDataObject As ChunkMetadata = JsonConvert.DeserializeObject(Of ChunkMetadata)(chunkMetadata)

            ' ...
            ' Perform security checks here
            ' ...

            ' Creates a directory for temporary files if it does not exist
            If (Not Directory.Exists(tempFileLocation)) Then
                Directory.CreateDirectory(tempFileLocation)
            End If

            Dim tempFilePath = Path.Combine(tempFileLocation, metaDataObject.FileGuid + ".tmp")

            ' Appends the chunk to the file
            AppendContentToFile(tempFilePath, file)

            ' Saves the file if all chunks are received
            If (metaDataObject.Index = (metaDataObject.TotalCount - 1)) Then
                System.IO.File.Copy(tempFilePath, Path.Combine(targetLocation, metaDataObject.FileName))
            End If
        End If
    Catch ex As Exception
        Throw New HttpException("Bad request")
    End Try
    Return New EmptyResult()
End Function

Function AppendContentToFile(path As String, content As HttpPostedFileBase)
    Using stream As New FileStream(path, FileMode.Append, FileAccess.Write)
        content.InputStream.CopyTo(stream)
        CheckMaxSize(stream)
    End Using
End Function

Function CheckMaxSize(stream As FileStream)
    If (stream.Length > 1024*400000) Then
        Throw New Exception("File is too large")
    End If
End Function
See Also