HTML 5 Drag and Drop File Upload ASP.Net Core

Featured ASP.Net Javascript

HTML 5 Drag and drop file upload is a very common feature in modern web applications. It allows users to upload one or multiple files by dragging and dropping them into the upload container.

In this tutorial, I will walk you through how this can be implemented without any third party plugin or library in ASP.Net Core.

What we are building

Below is the screenshot of what we will be building in the article.

drag-and-drop-file-upload-asp-net-core-mvc-full-app

HTML Markup

Although this has absolutely nothing to do with drag and drop. I just want to shared with you how the drag and drop container is been built.

<div class="main-wrap">
    <h2 style="text-align:center">Drag and Drop File Upload</h2>
    <h3 style="text-align:center">ASP.Net Core</h3>
    <div class="upload-container">
        <div class="upload_box">
            <input style="margin-left:-99999999px" multiple type="file" name="file" id="file">
            <div class="no_file">
                <h1 style="text-align:center">
                    <svg style="width:5rem" viewBox="0 0 72 72">
                        <path d="M36.493 72C16.118 72 0 55.883 0 36.493 0 16.118 16.118 0 36.493 0 55.882 0 72 16.118 72 36.493 72 55.882 55.883 72 36.493 72zM34 34h-9c-.553 0-1 .452-1 1.01v1.98A1 1 0 0 0 25 38h9v9c0 .553.452 1 1.01 1h1.98A1 1 0 0 0 38 47v-9h9c.553 0 1-.452 1-1.01v-1.98A1 1 0 0 0 47 34h-9v-9c0-.553-.452-1-1.01-1h-1.98A1 1 0 0 0 34 25v9z" fill="#409fff" fill-rule="nonzero">
                        </path>
                    </svg>
                </h1>
                <h3>
                    Drag and drop files here
                </h3>
                <p>Or</p>
                 
                <button class="btn btn-outline-primary browse-file">Browse Files</button>
            </div>
        </div>
    </div>
</div>

The CSS

To make it look great I have added the css below.

.main-wrap {
    padding: 5rem;
    position: relative;
}
.upload-container {
    z-index: 9999999;
    height: 362px;
    width: 682px;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}
.upload_box {
    background: #262b38;
    height: 360px;
    width: 680px;
    outline: 2px dashed #92b0b3;
    outline-offset: -10px;
    border-radius: 10px;
    cursor: pointer;
}
    .upload_box .no_file {
        padding: 50px 80px;
        text-align: center;
        position: absolute;
        top: auto;
        bottom: auto;
        left: 0;
        right: 0;
    }
        .upload_box .no_file h3,p {
            color: #92b0b3;
            font-size: 20px;
        }

ASP.Net Core Controller

In the home controller of the ASP.Net Core MVC, create an action result named upload. This method will receive file(e) from the view. In the constructor of the controller, inject IWebHostEnvironment interface as this is what will give us access to the WebRootPath in other to set the upload path in the application.

The upload method should have the following code.

 public IActionResult upload()
        {
            var files = Request.Form.Files;
            var uploadRootPath = Path.Combine(_environment.WebRootPath, "uploads");
            foreach (var item in files)
            {
                var uploadPath = Path.Combine(uploadRootPath, item.FileName);
                using(FileStream stream =new FileStream(uploadPath,FileMode.Create))
                {
                    item.CopyTo(stream);
                }
                
            }
            return Json(new { error = false });
        }

HTML 5 Drag and Drop Events

HTML 5 drag and drop uses the DOM event model and drag event inherited from mouse events A typical drag operation begins when a user selects a draggable element, drags the element to a droppable element, and then releases the dragged element.

During drag operations, several event types are fired, and some events might fire many times, such as the drag and dragover events.

Each drag event type has an associated global event handler but in our own case we will be making use of just three of them namely dragover, dragleave, and drop.

Preventing Default Browser Behavior

By default, when a file is drag onto a web page, the browser loads the local file as if it is a new page. To prevent this from happening we will add event listener to the window that calls preventDefault() and stopPropagation() on all dragover and drop events.

$("html").on("dragover", function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
});
$("html").on("drop", function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
});

Dragover

In the dragover event, the drop target detects that an item is being dragged over it. What we will be doing here is to set the opacity of the upload container for interactivity sake. That means whenever a user drag file(s) over the upload area we want the use to feel it by changing the opacity of the container.

$('.upload-container').on('dragover', function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
    $('.upload_box').css("opacity", 0.4);
});

Dragleave

In the dragleave event, the drop target detects that an item is being dragged out of it. Here we will set the upload area opacity back to 1 from the previous 0.4.

$('.upload-container').on('dragleave', function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
    $('.upload_box').css("opacity", 1);
});

Drop Event

This event fires whenever the file in dropped on the target. Here is where we will use the datatransfer interface to get the dropped file.

Each DataTransfer object contains an items property, which is a list of DataTransferItem objects. A DataTransferItem object represents a single drag item, each with a kind property (either string or file) and a type property for the data item’s MIME type. The DataTransferItem object also has methods to get the drag item’s data.

The DataTransferItemList object is a list of DataTransferItem objects. The list object has methods to add a drag item to the list, remove a drag item from the list, and clear the list of all drag items.

$('.upload-container').on('drop', function (evt) {
        evt.preventDefault();
        evt.stopPropagation();
        $(".no_file").hide();
        $('.upload_box').css("opacity", 1);
        var droppedFiles = evt.originalEvent.dataTransfer.files;
        var formData = new FormData();
        $.each(droppedFiles, function (i, v) {
            
            formData.append('file', v);
        });
})

The above code is self explanatory, we tapped into the event and get the dropped files from the dataTransfer interface and the use jQuery.each to append each file into FormData.

Choosing file the traditional way

Sometimes dragging & dropping files may not be the best way to select files for upload. Especially when a user is using a small screen size computer or a mobile device. Therefore it would be nice to let users choose the method they prefer. Notice that in the html markup, we have a file input element for this purpose.

<input style="margin-left:-99999999px" multiple type="file" name="file" id="file">

Click Event to chose file

We also need to handle the click event if user prefer to choose file the traditional way.

$("#file").change(function () {
    var selectedFiles = $(this)[0].files;
    var formData = new FormData();
    $.each(selectedFiles, function (i, v) {
        formData.append('file', v);
    });
});

What have done in the above code is similar to what we did earlier, but here we are getting the selected files from the input element rather than from the dataTransfer interface.

 

Ajax Upload

We will be sending the selected files to the server side via jQuery.ajax Post. Let’s make a function that will be responsible for that.

function uploadFiles(formdata) {
    return $.ajax({
        url: '/home/upload',
        type: 'post',
        data: formdata,
        contentType: false,
        processData: false,
        dataType: 'json',
    })
}

Notice that content type and process data are both set to false, this is very important.

Display Success/Error Message

There is need to give the user the correct feedback about the operation. The upload may be successful or fail. For this, we will be using Bootstrap Alert, alert-success for success message and alert-danger for error message

    var $alert = $(".alert");
    $.when(uploadFiles(formData)).then(function (res) {
        if (res.error === false) {
            $alert.addClass('alert-success').html("Your files has been uploaded");
        } else {
            $alert.addClass('alert-danger').html("An error occured while uploading files");
        }
    }).fail(function (err) {
        $alert.addClass('alert-danger').html("An error occured while uploading files");
    });

The Complete Javascript Code

The whole javascript code in the project should look like this:


$("html").on("dragover", function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
});
$("html").on("drop", function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
});
function uploadFiles(formdata) {
    return $.ajax({
        url: '/home/upload',
        type: 'post',
        data: formdata,
        contentType: false,
        processData: false,
        dataType: 'json',
    })
}
$(".browse-file").click(function (evt) {
    evt.preventDefault();
    $("#file").click();
});
$('.upload-container').on('dragover', function (evt) {
    evt.preventDefault();
    evt.stopPropagation();
    $('.upload_box').css("opacity", 0.4);
})
    .on('dragleave', function (evt) {
        evt.preventDefault();
        evt.stopPropagation();
        $('.upload_box').css("opacity", 1);
    })
    .on('drop', function (evt) {
        evt.preventDefault();
        evt.stopPropagation();
        $(".no_file").hide();
        $('.upload_box').css("opacity", 1);
        var droppedFiles = evt.originalEvent.dataTransfer.files;
        var formData = new FormData();
        $.each(droppedFiles, function (i, v) {
            
            formData.append('file', v);
        });
        var $alert = $(".alert");
        $.when(uploadFiles(formData)).then(function (res) {
            if (res.error === false) {
                $alert.addClass('alert-success').html("Your files has been uploaded");
            } else {
                $alert.addClass('alert-danger').html("An error occured while uploading files");
            }
        }).fail(function (err) {
            $alert.addClass('alert-danger').html("An error occured while uploading files");
        });
    });
$("#file").change(function () {
    var selectedFiles = $(this)[0].files;
    var formData = new FormData();
    $.each(selectedFiles, function (i, v) {
        formData.append('file', v);
    });
    var $alert = $(".alert");
    $.when(uploadFiles(formData)).then(function (res) {
        if (res.error === false) {
            $alert.addClass('alert-success').html("Your files has been uploaded");
        } else {
            $alert.addClass('alert-danger').html("An error occured while uploading files");
        }
    }).fail(function (err) {
        $alert.addClass('alert-danger').html("An error occured while uploading files");
    });
});

That’s it! This article could have been even longer, but I think this will get you going with a responsible drag and drop file upload feature on your own ASP.Net Core projects.

Similar Posts