clement clement - 7 months ago 46
Javascript Question

from file upload to dropzone

I'm using multi file upload with other fields in my project and I want to overhide the basic html file upload by dropzone, so I don't want to send files trough ajax, I just want to drop files, then fill the form and send files to server at the same time that ther fields (when user press "Send").

Here is the working current form without dropzone that works perfectly:

<form action="/Document/Document/Create" enctype="multipart/form-data" method="post">
<div class="form-horizontal">
<hr>

<div class="form-group">
<div>
<input name="files" type="file" id="files" multiple>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="sourcePath">Source</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Source est requis." id="sourcePath" name="sourcePath" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="sourcePath" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="name">Nom</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Nom est requis." id="name" name="name" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="name" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="reference">Référence</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Référence est requis." id="reference" name="reference" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="reference" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default">
</div>
</div>
</div>
</form>


This is what I've tried but it looks it doesn't work (no droppable zone, upload button still there)

HTML

<div id="dropzone" class="dropzone">
<div class="fallback">
<input name="files" type="file" id="files" multiple />
</div>
</div>


JS

// DropZone
Dropzone.options.dropzone = {
paramName: "files", // The name that will be used to transfer the file
maxFilesize: 10, // MB
//uploadMultiple: true,
autoProcessQueue: false,
accept: function (file, done) {
if (file.name == "justinbieber.jpg") {
done("Naha, you don't.");
}
else { done(); }
}
};


EDIT:

thanks to melc, it looks great but no "files" are posted. here is the post content. There are more fields that in the example because example I gave is simpler

Request URL:http://localhost:28790/Document/Document/Create
Request Headers
Provisional headers are shown
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryA5AptmHYANCvKIsO
Origin:http://localhost:28790
Referer:http://localhost:28790/Document/Document/Create
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36
Request Payload
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="__RequestVerificationToken"

W9DAH4P8rACAn6FeB2lh6uhrS1-h25xvhxp0C3q78tqnKzQuzvphoZEyTu46VniBpTzcQ89JxqKjxy9eoTayMjzSJMIjH-u0Fs0toxe4oy39K6-s6uOcM7dicZm8LefBpZMfUqOQwON8Z6rtmAt-8w2
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="sourcePath"

fdgh
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="name"

gfdhfd
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="reference"

fdghdfrg
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="isActive"

true
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="isActive"

false
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="recyclingSpan"

2
------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="documentType.id"


------WebKitFormBoundaryA5AptmHYANCvKIsO
Content-Disposition: form-data; name="trainer.id"


------WebKitFormBoundaryA5AptmHYANCvKIsO--


and here's the HTML generated:

<div class="main">
<h2>Create</h2>
<form action="/Document/Document/Create" enctype="multipart/form-data" method="post" novalidate="novalidate">
<div class="form-horizontal">
<hr>
<input name="__RequestVerificationToken" type="hidden" value="qvsqgYhMtW6Tc_Cn5st61PPI1jULgz6pMB9iGZS2FPTAyR8HPSDJII0x_Oj0nuTFHrlvwl2HDA3s4sllfOSVDMXFyUnsCeVjxruyGN5goirG73BmfqV6K868Ucj9DN5Tsbssisp-7iiHzSoYCmVQGw2">

<div class="form-group">
<label class="control-label col-md-2" for="sourcePath">Source</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Source est requis." id="sourcePath" name="sourcePath" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="sourcePath" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="name">Nom</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Nom est requis." id="name" name="name" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="name" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="reference">Référence</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Référence est requis." id="reference" name="reference" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="reference" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="isActive">Document actif?</label>
<div class="col-md-10">
<div class="checkbox">
<input class="check-box" data-val="true" data-val-required="Le champ Document actif? est requis." id="isActive" name="isActive" type="checkbox" value="true">
<input name="isActive" type="hidden" value="false">
<span class="field-validation-valid text-danger" data-valmsg-for="isActive" data-valmsg-replace="true"></span>
</div>
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="recyclingSpan">Délai de recyclage</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-number="Le champ Délai de recyclage doit être un nombre." data-val-range="Le champ Délai de recyclage doit être compris entre 1 et 999." data-val-range-max="999" data-val-range-min="1" data-val-required="Le champ Délai de recyclage est requis." id="recyclingSpan" name="recyclingSpan" type="number" value="0">
<span class="field-validation-valid text-danger" data-valmsg-for="recyclingSpan" data-valmsg-replace="true"></span> Mois
</div>
</div>

<div class="form-group">
<label class="control-label col-md-2" for="documentType">Type de document</label>
<div class="col-md-10">
<select class="form-control" data-val="true" data-val-number="Le champ id doit être un nombre." data-val-required="Le champ id est requis." id="documentType_id" name="documentType.id" style="display: none;">
<option value=""></option>
<option value="2">ypê de doc a supprimer</option>
<option value="3">Audit du TMB</option>
</select>
<div class="chosen-container chosen-container-single" style="width: 550px;" title="" id="documentType_id_chosen"><a class="chosen-single chosen-default" tabindex="-1"><span>Select an Option</span><div><b></b></div></a>
<div class="chosen-drop">
<div class="chosen-search">
<input type="text" autocomplete="off">
</div>
<ul class="chosen-results"></ul>
</div>
</div>
<span class="field-validation-valid text-danger" data-valmsg-for="documentType.id" data-valmsg-replace="true"></span>
</div>
</div>

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default">
</div>
</div>
</div>
</form>

<div id="dropzone" class="dropzone dz-clickable" style="height:100px;margin-bottom: 30px">

<div class="dz-default dz-message"><span>Drop files here to upload</span>
</div>
</div>

<div>
<a href="/Document/Document">Retourner à la liste des éléments</a>
</div>
</div>


with js

// DropZone
Dropzone.options.dropzone = {
paramName: "files", // The name that will be used to transfer the file
maxFilesize: 10, // MB
//uploadMultiple: true,
autoProcessQueue: false,
url: "/file/post",
accept: function (file, done) {
if (file.name == "justinbieber.jpg") {
done("Naha, you don't.");
}
else { done(); }
}
};

$(document).ready(function () {
// stuff
});

Answer

When using dropzone it is possible to send additional data based on the following three approaches.

  1. Apply dropzone to a form with input fields.
  2. Apply dropzone to a form with hidden input fields. The values of the fields may be populated with js. (http://www.dropzonejs.com/#tips)
  3. Use params property. (http://www.dropzonejs.com/#tips)
  4. Append form data to each file via the sending event and the formData parameter. (http://www.dropzonejs.com/#tips)

The first approach seems to fit the needs of the op. Guidance for this solution can be found here https://github.com/enyo/dropzone/wiki/Combine-normal-form-with-Dropzone.

Please find a rough but successful attempt of this solution based on your example (it is required to check the network calls from browser dev tools to see the data that get sent),

http://jsbin.com/ruvedigifu/1/edit?html,js,output

The post request payload from the example has the following form,

------WebKitFormBoundary0Mm4s3UDxfPPh1DR
Content-Disposition: form-data; name="sourcePath"

value of field1
------WebKitFormBoundary0Mm4s3UDxfPPh1DR
Content-Disposition: form-data; name="name"

value of field2
------WebKitFormBoundary0Mm4s3UDxfPPh1DR
Content-Disposition: form-data; name="reference"

value of field3
------WebKitFormBoundary0Mm4s3UDxfPPh1DR
Content-Disposition: form-data; name="null"

Create
------WebKitFormBoundary0Mm4s3UDxfPPh1DR
Content-Disposition: form-data; name="file[0]"; filename="test1.txt"
Content-Type: text/plain


------WebKitFormBoundary0Mm4s3UDxfPPh1DR--

UPDATE - based on more complex form

Please find a working example here,

http://jsbin.com/zobevazega/1/edit?html,js,output

the code,

html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/4.0.1/dropzone.js"></script>
</head>
<body>
<div class="main">
    <h2>Create</h2>
    <form action="/" enctype="multipart/form-data" method="post" novalidate="novalidate" id="dropzone" class="dropzone dz-clickable" style="height:100px;margin-bottom: 30px">
        <div class="form-horizontal">
            <hr>
            <input name="__RequestVerificationToken" type="hidden" value="qvsqgYhMtW6Tc_Cn5st61PPI1jULgz6pMB9iGZS2FPTAyR8HPSDJII0x_Oj0nuTFHrlvwl2HDA3s4sllfOSVDMXFyUnsCeVjxruyGN5goirG73BmfqV6K868Ucj9DN5Tsbssisp-7iiHzSoYCmVQGw2">

            <div class="form-group">
                <label class="control-label col-md-2" for="sourcePath">Source</label>
                <div class="col-md-10">
                    <input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Source est requis." id="sourcePath" name="sourcePath" type="text" value="">
                    <span class="field-validation-valid text-danger" data-valmsg-for="sourcePath" data-valmsg-replace="true"></span>
                </div>
            </div>

            <div class="form-group">
                <label class="control-label col-md-2" for="name">Nom</label>
                <div class="col-md-10">
                    <input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Nom est requis." id="name" name="name" type="text" value="">
                    <span class="field-validation-valid text-danger" data-valmsg-for="name" data-valmsg-replace="true"></span>
                </div>
            </div>

            <div class="form-group">
                <label class="control-label col-md-2" for="reference">Référence</label>
                <div class="col-md-10">
                    <input class="form-control text-box single-line" data-val="true" data-val-required="Le champ Référence est requis." id="reference" name="reference" type="text" value="">
                    <span class="field-validation-valid text-danger" data-valmsg-for="reference" data-valmsg-replace="true"></span>
                </div>
            </div>

            <div class="form-group">
                <label class="control-label col-md-2" for="isActive">Document actif?</label>
                <div class="col-md-10">
                    <div class="checkbox">
                        <input class="check-box" data-val="true" data-val-required="Le champ Document actif? est requis." id="isActive" name="isActive" type="checkbox" value="true">
                        <input name="isActive" type="hidden" value="false">
                        <span class="field-validation-valid text-danger" data-valmsg-for="isActive" data-valmsg-replace="true"></span>
                    </div>
                </div>
            </div>

            <div class="form-group">
                <label class="control-label col-md-2" for="recyclingSpan">Délai de recyclage</label>
                <div class="col-md-10">
                    <input class="form-control text-box single-line" data-val="true" data-val-number="Le champ Délai de recyclage doit être un nombre." data-val-range="Le champ Délai de recyclage doit être compris entre 1 et 999." data-val-range-max="999" data-val-range-min="1" data-val-required="Le champ Délai de recyclage est requis." id="recyclingSpan" name="recyclingSpan" type="number" value="0">
                    <span class="field-validation-valid text-danger" data-valmsg-for="recyclingSpan" data-valmsg-replace="true"></span> Mois
                </div>
            </div>

            <div class="form-group">
                <label class="control-label col-md-2" for="documentType">Type de document</label>
                <div class="col-md-10">
                    <select class="form-control" data-val="true" data-val-number="Le champ id doit être un nombre." data-val-required="Le champ id est requis." id="documentType_id" name="documentType.id" style="display: none;">
                        <option value=""></option>
                        <option value="2">ypê de doc a supprimer</option>
                        <option value="3">Audit du TMB</option>
                    </select>
                    <div class="chosen-container chosen-container-single" style="width: 550px;" title="" id="documentType_id_chosen"><a class="chosen-single chosen-default" tabindex="-1"><span>Select an Option</span><div><b></b></div></a>
                        <div class="chosen-drop">
                            <div class="chosen-search">
                                <input type="text" autocomplete="off">
                            </div>
                            <ul class="chosen-results"></ul>
                        </div>
                    </div>
                    <span class="field-validation-valid text-danger" data-valmsg-for="documentType.id" data-valmsg-replace="true"></span>
                </div>
            </div>

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default">
                </div>
            </div>
        </div>
    </form>



    <div>
        <a href="/Document/Document">Retourner à la liste des éléments</a>
    </div>

</div>

</body>
</html>

js

Dropzone.options.dropzone = { 
  url:"/",
  // The configuration we've talked about above
  autoProcessQueue: false,
  uploadMultiple: true,
  parallelUploads: 100,
  maxFiles: 100,
  // The setting up of the dropzone
  init: function() {
    var myDropzone = this;

    // First change the button to actually tell Dropzone to process the queue.
   console.log(this.element); this.element.querySelector("input[type=submit]").addEventListener("click", function(e) {
      // Make sure that the form isn't actually being sent.
      e.preventDefault();
      e.stopPropagation();
      myDropzone.processQueue();
    });

    // Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
    // of the sending event because uploadMultiple is set to true.
    this.on("sendingmultiple", function() {
      // Gets triggered when the form is actually being sent.
      // Hide the success button or the complete form.
    });
    this.on("successmultiple", function(files, response) {
      // Gets triggered when the files have successfully been sent.
      // Redirect user or notify of success.
    });
    this.on("errormultiple", function(files, response) {
      // Gets triggered when there was an error sending the files.
      // Maybe show form again, and notify user of error
    });
  }

};

request payload

------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="__RequestVerificationToken"

qvsqgYhMtW6Tc_Cn5st61PPI1jULgz6pMB9iGZS2FPTAyR8HPSDJII0x_Oj0nuTFHrlvwl2HDA3s4sllfOSVDMXFyUnsCeVjxruyGN5goirG73BmfqV6K868Ucj9DN5Tsbssisp-7iiHzSoYCmVQGw2
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="sourcePath"

a
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="name"

b
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="reference"

c
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="isActive"

false
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="recyclingSpan"

23
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="documentType.id"


------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="null"


------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="null"

Create
------WebKitFormBoundaryWtbOVsPX2XBRTti4
Content-Disposition: form-data; name="file[0]"; filename="test1.txt"
Content-Type: text/plain


------WebKitFormBoundaryWtbOVsPX2XBRTti4--