File Upload trong Asp.Net MVC sử dụng DropZone

Trước đây mình có làm một ví dụ tích hợp DropZone để xây dựng chức năng Upload Multiple File trong WebForm, hôm nay mình chia sẻ thêm một ví dụ về cách tích hợp DropZone vào Asp.Net MVC

Mình có giới thiệu qua một số đặc điểm cơ bản của DropZone tại đây: Drag & Drop upload multiple file với Asp.net C# & Dropzone.js

1. Cài đặt DropZone vào Project.

Để cài đặt dropzone, các bạn có thể download trực tiếp từ https://github.com/enyo/dropzone sau đó copy file js & css vào project của mình. Hoặc chạy nuget command dưới đây

Install-Package dropzone -Version 4.2.0

2. Tích hợp DropZone vào Project

Đầu tiên trong Controller ta cần viết một hàm để thực hiện việc upload và lưu các file được lựa chọn lên server (trong ví dụ này mình sẽ lưu các file vào folder Uploads của project)

[HttpPost, ValidateAntiForgeryToken]
        public ActionResult SaveUploadFile(int CategoryId)
        {
            var fName = string.Empty;
            Photo result = new Photo();

            foreach (string fileName in Request.Files)
            {
                HttpPostedFileBase file = Request.Files[fileName];
                fName = file.FileName;
                if(file != null && file.ContentLength > 0)
                {
                    string UploadFolder = "Category_" + CategoryId;
                    var originalDirectory = new DirectoryInfo(string.Format("{0}Uploads", Server.MapPath(@"\")));
                    string pathString = Path.Combine(originalDirectory.ToString(), UploadFolder);

                    bool isExists = Directory.Exists(pathString);
                    if (!isExists)
                        Directory.CreateDirectory(pathString);

                    string RandomName = Guid.NewGuid() + Path.GetExtension(fName);
                    var path = string.Format("{0}\\{1}", pathString, RandomName);
                    file.SaveAs(path);

                    result.Name = fName;
                    result.Url = "/Uploads/" + UploadFolder + "/" + RandomName;
                }
            }

            return Json(new { Name = result.Name, UrlPhoto = result.Url }, JsonRequestBehavior.AllowGet);
        }

Hàm upload trên sẽ trả về thông tin file được upload khi thành công (Name & Url) để các bạn xử lý tiếp nếu cần. Ở hàm này mình làm upload file lên các SubFolder (Category_1, Category_2) với mục đích phân loại, ví dụ sau này có thể upload image lên các folder được lựa chọn :).

Ở _Layout.cshtml ta kéo thư viện css & js của DropZone vào.

//head tag
<link href="~/Scripts/dropzone/basic.css" rel="stylesheet" />
<link href="~/Scripts/dropzone/dropzone.css" rel="stylesheet" />
//footer page
<script src="~/Scripts/dropzone/dropzone.js"></script>
@RenderSection("scripts", required: false)

Chú ý thư viện js của DropZone phải để nằm dưới thư viện JQuery

Ở Index.cshtml ta cần thêm form upload của dropzone 

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div id="dZUpload" class="dropzone">
        <div class="dz-default dz-message"></div>
    </div>
    <hr />
    <a href="javascript:;" id="btnSubmit" class="btn btn-primary btn-lg">Upload</a>
}

Tiếp theo thêm hàm javascript để xử lý việc upload, hàm này sẽ gọi hàm Server Site viết trong Controller ở trên

@section scripts{
    <script>
        Dropzone.autoDiscover = false;
        $(document).ready(function () {
            var UrlUpload = "/Home/SaveUploadFile?CategoryId=1";
            var myDropzone = new Dropzone("#dZUpload", {
                url: UrlUpload,
                maxFiles: 20,
                addRemoveLinks: true,
                maxFilesize: 1,
                acceptedFiles: "image/jpeg, image/jpg, image/png",
                autoProcessQueue: false,
                parallelUploads: 1,
                init: function () {
                    var startUpload = document.getElementById('btnSubmit');
                    var myDropzone = this;
                    startUpload.addEventListener("click", function () {
                        myDropzone.processQueue();
                    });

                    this.on("processing", function (file) {
                        myDropzone.options.url = "/Home/SaveUploadFile?CategoryId=1";
                    });

                    this.on("success", function () {
                        myDropzone.options.autoProcessQueue = true;
                    });

                    this.on("queuecomplete", function () {
                        setTimeout(function () {
                            myDropzone.options.autoProcessQueue = false;
                            myDropzone.removeAllFiles(true);
                        }, 3000);
                    });
                },
                success: function (file, response) {
                    file.previewElement.classList.add("dz-success");
                },
                error: function (file, response) {
                    file.previewElement.classList.add("dz-error");
                    $(file.previewElement).find('.dz-error-message').text(response);
                    console.log(response);
                }
            });

            $('#btnSubmit').click(function () {
                myDropzone.processQueue();
            });
        });
    </script>
    
}

3. Custom AntiForgeryToken

DropZone thực hiện upload file lên server bằng cách gọi hàm SaveUploadFile thông qua ajax method. Do vậy nếu muốn implement AntilForgeryToken vào chức năng này, chúng ta cần modify một chút.

Chúng ta tạo mới 1 class với tên ValidateJsonAntiForgeryTokenAttribute.cs

using System;
using System.Web.Helpers;
using System.Web.Mvc;

namespace DropZoneUploadMVC5
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
    {

        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            var httpContext = filterContext.HttpContext;
            var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
            AntiForgery.Validate(cookie != null ? cookie.Value : null, 
                httpContext.Request.Headers["__RequestVerificationToken"]);
        }
    }
}

Trong hàm SaveUploadFile ở HomeController vừa viết ở trên, ta chỉnh lại như sau

//[HttpPost, ValidateAntiForgeryToken]
[HttpPost, ValidateJsonAntiForgeryToken]
public ActionResult SaveUploadFile(int CategoryId)
{

Và cuối cùng trong hàm javascript ở Index.cshtml ta cần thêm token vào.

$(document).ready(function () {
            var token = $('input[name="__RequestVerificationToken"]').val(); //add this line
            var UrlUpload = "/Home/SaveUploadFile?CategoryId=1";
            var myDropzone = new Dropzone("#dZUpload", {
                url: UrlUpload,
                headers: { "__RequestVerificationToken": token },   //add this line
                maxFiles: 20,
                addRemoveLinks: true,

Vậy là xong, các bạn có thể download ví dụ dưới đây để xem rõ hơn.

Download Source

Related Post


Đếm số ngươi Online website với SignalR
Wednesday, June 28, 2017
SignalR là một thư viện cho phép các lập trình viên .Net đơn giản hóa việc xây dựng các chức năng xử lý real-time trong quá trình phát triển ứng dụng. Nó cho phép server đẩy nội dung tới client một cách tức thì ngay khi có sự kiện xẩy ra, chứ không phải server đợi client yên cầu rồi trả về nội dung tương ứng như giao thức HTTP truyền thống. Trong ví dụ này mình làm một chức năng nhỏ đó là đếm số người online trên website với SignalR, ngay khi có người connect vào website, server sẽ nhận biết và trả về client ngay lập tức.
Sử dụng Bundling và Minification trong Web Forms để tối ưu thời gian tải trang
Friday, May 26, 2017
Bundling và Minification là hai công nghệ được sử dụng trong Asp.Net 4.5 để cải thiện và tối ưu thời gian tải trang của bạn. Bundling và Minification tối ưu thời gian tải bằng cách nhóm các file css & js lại với nhau (Bundling) , và tiến hành loại bỏ các khoảng trống, xuống dòng, comment để giảm kích thước file (Minification)...
Search
Category

Blog Archive

Đăng ký nhận bài mới