javascripthtmlasp.net-core-mvcdropzoneiformfile

How to Integrate Dropzone.js with ASP.NET Core MVC?


I want to upload some documents in my database using an IFormFile. On client side I'm using Dropzone.js but it's not working properly. Whenever I hit Submit button it sends a null value in parameter. I Have two queries. 1. How to send Document (image/PDF) to the action method. 2. How to redesign (change style of) Dropzone. (if someone explain the flow of dropzone then it would be very useful)

Here is my HTML Code

<form asp-action="AddDocument" asp-controller="Transactions" method="post" enctype="multipart/form-data" class="dropzone dz-clickable form-horizontal form-bordered" id="dropzoneForm">
    <div class="form-group form-actions">
        <div class="col-md-9 col-md-offset-4">
            <button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-floppy-o"></i> Upload</button>
        </div>
    </div>
</form> 

JS Code:

$(function () {
            Dropzone.options.dropzoneForm = {
                paramName: "DocumentPhotos", // The name that will be used to transfer the file
                autoProcessQueue: false,
                uploadMultiple: true,
                parallelUploads: 100,
                accept: function (file, done) {
                    done();
                }
            };
        });

and here is my Server-Side language code:

        [HttpPost]
        public async Task<IActionResult> AddDocument(IEnumerable<IFormFile> DocumentPhotos)
        {

            if (DocumentPhotos!= null)
            {
                TransactionViewModel viewModel = new TransactionViewModel();
                var documentModel = viewModel.TransactionModel.TransactionDocuemnt;
                foreach (var item in DocumentPhotos)
                {

                    using (MemoryStream stream = new MemoryStream())
                    {
                        await item.CopyToAsync(stream);
                        documentModel.DocumentPhoto = stream.ToArray();
                    }
                    documentModel.DocumentName = item.FileName;
                    documentModel.SrNo = 1;
                    documentModel.SocietyRid = UserSessionState.ApplicationUser.SocietyRid;
                }
            }

            return PartialView("TransactionDocumentForm", transactionViewModel);
        }

Scripts and CSS used (all files are downloaded from Dropzone.js):

<link rel="stylesheet" href="~/css/basic.css" />
<link rel="stylesheet" href="~/css/dropzone.css" />
<script type="text/javascript" src="~/js/dropzone.js"></script>
<script type="text/javascript" src="~/js/dropzone-amd-module.js"></script>

Solution

  • If you have the option uploadMultiple set to true, then Dropzone will append [] to the paramName. After looking at the request from a html5 multiple file upload I noticed the request does not add the indexes to the filename (files[n]). Dropzone.js does this so there is a work around. If you add the paramName option to Dropzone JS config and have it call a method which returns files you will get the same behaviour as the html5 multiple file upload, which is using the exact same file name for each of the files. This is no problem, except if you would need the ordering. You could also refer to this link for more details on Configuration options of Dropzone.js

    function myParamName() {
        return "DocumentPhotos";
    }
    
    Dropzone.options.dropzoneForm = {
       paramName: myParamName, 
       //other configuration options
    }
    

    autoProcessQueue: false tells Dropzone not to automatically upload the file when you drop it, as it will by default. Since Dropzone will now not auto-upload the files, you need to manually tell it to do that when you click your button. So you need an event handler for that button click, which tells Dropzone to do the upload:

     <button type="submit" id="submit" class="btn btn-sm btn-primary"><i class="fa fa-floppy-o"></i> Upload</button>
    
     var wrapperThis = this;
                  
     $("#submit").click(function (e) {
           e.preventDefault();
           wrapperThis.processQueue();
     });
    

    The complete code

    <form asp-action="AddDocument" asp-controller="Home" method="post" enctype="multipart/form-data" class="dropzone dz-clickable form-horizontal form-bordered" id="dropzoneForm">
      <div class="form-group form-actions">
        <div class="col-md-9 col-md-offset-4">
            <button type="submit" id="submit" class="btn btn-sm btn-primary"><i class="fa fa-floppy-o"></i> Upload</button>
        </div>
      </div>
    </form>
    
    @section Scripts
    {
      <link rel="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/dropzone.css" />
      <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/dropzone.js"> </script>
      <script>
           function myParamName() {
               return "DocumentPhotos";
            }
            Dropzone.options.dropzoneForm = {
                autoProcessQueue: false,
                paramName: myParamName, // The name that will be used to transfer each file
                uploadMultiple: true,
                parallelUploads: 100,
                init: function () {
                    console.log("active");
                    var wrapperThis = this;
                   
                    $("#submit").click(function (e) {
                        e.preventDefault();
                        wrapperThis.processQueue();
                    });
                },
                accept: function (file, done) {
                    done();
                }
            };
      
    </script>
    }