Integrating Dropzone.js into existing HTML form with other fields
Solution 1
Here's another way to do it: add a div
in your form with a classname dropzone, and implement dropzone programmatically.
HTML :
<div id="dZUpload" class="dropzone">
<div class="dz-default dz-message"></div>
</div>
JQuery:
$(document).ready(function () {
Dropzone.autoDiscover = false;
$("#dZUpload").dropzone({
url: "hn_SimpeFileUploader.ashx",
addRemoveLinks: true,
success: function (file, response) {
var imgName = response;
file.previewElement.classList.add("dz-success");
console.log("Successfully uploaded :" + imgName);
},
error: function (file, response) {
file.previewElement.classList.add("dz-error");
}
});
});
Note : Disabling autoDiscover, otherwise Dropzone will try to attach twice
Solution 2
I had the exact same problem and found that Varan Sinayee's answer was the only one that actually solved the original question. That answer can be simplified though, so here's a simpler version.
The steps are:
Create a normal form (don't forget the method and enctype args since this is not handled by dropzone anymore).
Put a div inside with the
class="dropzone"
(that's how Dropzone attaches to it) andid="yourDropzoneName"
(used to change the options).Set Dropzone's options, to set the url where the form and files will be posted, deactivate autoProcessQueue (so it only happens when user presses 'submit') and allow multiple uploads (if you need it).
Set the init function to use Dropzone instead of the default behavior when the submit button is clicked.
Still in the init function, use the "sendingmultiple" event handler to send the form data along wih the files.
Voilà ! You can now retrieve the data like you would with a normal form, in $_POST and $_FILES (in the example this would happen in upload.php)
HTML
<form action="upload.php" enctype="multipart/form-data" method="POST">
<input type="text" id ="firstname" name ="firstname" />
<input type="text" id ="lastname" name ="lastname" />
<div class="dropzone" id="myDropzone"></div>
<button type="submit" id="submit-all"> upload </button>
</form>
JS
Dropzone.options.myDropzone= {
url: 'upload.php',
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 5,
maxFiles: 5,
maxFilesize: 1,
acceptedFiles: 'image/*',
addRemoveLinks: true,
init: function() {
dzClosure = this; // Makes sure that 'this' is understood inside the functions below.
// for Dropzone to process the queue (instead of default form behavior):
document.getElementById("submit-all").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
dzClosure.processQueue();
});
//send all the form data along with the files:
this.on("sendingmultiple", function(data, xhr, formData) {
formData.append("firstname", jQuery("#firstname").val());
formData.append("lastname", jQuery("#lastname").val());
});
}
}
Solution 3
The "dropzone.js" is the most common library for uploading images. If you want to have the "dropzone.js" as just part of your form, you should do the following steps:
1) for the client side:
HTML :
<form action="/" enctype="multipart/form-data" method="POST">
<input type="text" id ="Username" name ="Username" />
<div class="dropzone" id="my-dropzone" name="mainFileUploader">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</div>
</form>
<div>
<button type="submit" id="submit-all"> upload </button>
</div>
JQuery:
<script>
Dropzone.options.myDropzone = {
url: "/Account/Create",
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
acceptedFiles: "image/*",
init: function () {
var submitButton = document.querySelector("#submit-all");
var wrapperThis = this;
submitButton.addEventListener("click", function () {
wrapperThis.processQueue();
});
this.on("addedfile", function (file) {
// Create the remove button
var removeButton = Dropzone.createElement("<button class='btn btn-lg dark'>Remove File</button>");
// Listen to the click event
removeButton.addEventListener("click", function (e) {
// Make sure the button click doesn't submit the form:
e.preventDefault();
e.stopPropagation();
// Remove the file preview.
wrapperThis.removeFile(file);
// If you want to the delete the file on the server as well,
// you can do the AJAX request here.
});
// Add the button to the file preview element.
file.previewElement.appendChild(removeButton);
});
this.on('sendingmultiple', function (data, xhr, formData) {
formData.append("Username", $("#Username").val());
});
}
};
</script>
2) for the server side:
ASP.Net MVC
[HttpPost]
public ActionResult Create()
{
var postedUsername = Request.Form["Username"].ToString();
foreach (var imageFile in Request.Files)
{
}
return Json(new { status = true, Message = "Account created." });
}
Solution 4
I have a more automated solution for this.
HTML:
<form role="form" enctype="multipart/form-data" action="{{ $url }}" method="{{ $method }}">
{{ csrf_field() }}
<!-- You can add extra form fields here -->
<input hidden id="file" name="file"/>
<!-- You can add extra form fields here -->
<div class="dropzone dropzone-file-area" id="fileUpload">
<div class="dz-default dz-message">
<h3 class="sbold">Drop files here to upload</h3>
<span>You can also click to open file browser</span>
</div>
</div>
<!-- You can add extra form fields here -->
<button type="submit">Submit</button>
</form>
JavaScript:
Dropzone.options.fileUpload = {
url: 'blackHole.php',
addRemoveLinks: true,
accept: function(file) {
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onloadend = function() {
let content = fileReader.result;
$('#file').val(content);
file.previewElement.classList.add("dz-success");
}
file.previewElement.classList.add("dz-complete");
}
}
Laravel:
// Get file content
$file = base64_decode(request('file'));
No need to disable DropZone Discovery and the normal form submit will be able to send the file with any other form fields through standard form serialization.
This mechanism stores the file contents as base64 string in the hidden input field when it gets processed. You can decode it back to binary string in PHP through the standard base64_decode()
method.
I don't know whether this method will get compromised with large files but it works with ~40MB files.
Solution 5
Enyo's tutorial is excellent.
I found that the sample script in the tutorial worked well for a button embedded in the dropzone (i.e., the form element). If you wish to have the button outside the form element, I was able to accomplish it using a click event:
First, the HTML:
<form id="my-awesome-dropzone" action="/upload" class="dropzone">
<div class="dropzone-previews"></div>
<div class="fallback"> <!-- this is the fallback if JS isn't working -->
<input name="file" type="file" multiple />
</div>
</form>
<button type="submit" id="submit-all" class="btn btn-primary btn-xs">Upload the file</button>
Then, the script tag....
Dropzone.options.myAwesomeDropzone = { // The camelized version of the ID of the form element
// The configuration we've talked about above
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 25,
maxFiles: 25,
// The setting up of the dropzone
init: function() {
var myDropzone = this;
// Here's the change from enyo's tutorial...
$("#submit-all").click(function (e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
}
}
Related videos on Youtube
Ben Thompson
Previous experience with Java, php, sql. Now attempting ios development. Java -> Objective C is ok. SQL -> Core Data much harder!!!
Updated on July 23, 2021Comments
-
Ben Thompson almost 3 years
I currently have a HTML form which users fill in details of an advert they wish to post. I now want to be able to add a dropzone for uploading images of the item for sale.
I have found Dropzone.js which seems to do most of what I need. However, when looking into the documentation, it appears that you need to specify the class of the whole form as
dropzone
(as opposed to just the input element). This then means that my entire form becomes the dropzone.Is it possible to use the dropzone in just part of my form, i.e. by only specifying the element as class "dropzone", rather than the whole form?
I could use separate forms, but I want the user to be able to submit it all with one button.
Alternatively, is there another library that can do this?
Many thanks
-
paul over 10 yearsYou cannot have a form inside a form and submit.
-
Aaron Hill over 9 yearsWhen I try this, the dropzone-previews container seems to be ignored. Dropzone just adds the previews to the bottom of the form. You will need to add 'previewsContainer: '.dropzone-previews',' to your configuration.
-
CSSian about 9 yearsThis doesn't answer the original question. The original question was how to use Dropzone with an existing form, not about the location of the button to trigger the action.
-
clement about 9 yearsWith that, he can't use the default submit button, it doesn't respond to his question
-
Satinder singh almost 9 years@clement: OP doesn't want to add 'dropzone' class in form tag, coz this make whole form as dropzone. So with my answer he can add separate div inside form tag or outside form like as popup modal and by jQuery initialize dropzone.
-
Satinder singh almost 9 yearsIts Asynchronous so file get save without submit button, On submit he can save uploaded files name into db
-
dangel almost 9 yearsbut this still doesn't use the original form to submit
-
Su4p over 8 yearsthis was my issue and you resolved it, ty @Satindersingh
-
Satinder singh over 8 years@Su4p : am glad it helps you, also you can check blog article link for details explanation along with resize image option while uploading
-
DigitalDesignDj over 8 years@dangel I thought that was what I wanted too, but I am very happy with the resulting solution. I suggest you just submit the uploads right away.
-
DigitalDesignDj over 8 yearsThis helped a lot, you can setup any element as a dropzone if you setup the url manually. I used the success handler to post the filename to a hidden/disabled field in the primary form.
-
Sato about 8 yearsThanks for the post! Solved my problem. Another quick question, this does not work when no images selected(to upload), how to solve this?
-
Felix G. about 8 yearsThis solution is nice and works, but it doesn't redirect to the next page anymore, because of preventing the default submit behavior.
-
Rusty about 8 yearsTo the beginners using Dropzone.js. To select a file, you will have to click on the div itself which is in this answer
<div class="dz-default dz-message"></div>
-
born2fr4g almost 8 years@TIIUNDER - its prepared for sending form info via ajax call without page reload - thats why there is e.preventDefault();
-
Edward Chopuryan over 7 yearsBTW: if you use controller action with model binding and submit your form like this the model will be empty. For some reason this method doesn't bind the actual data to the model.
-
doflamingo over 7 years@TIUNDER you can add redirect in success event
-
Matti over 6 yearsI basically used this approach, but due to apparent processing delays, in the end hooked up the file content processing under the
myDropzone.on("thumbnail", () => {})
event. Doing the processing immediately on"addedFile"
the file might still beundefined
upon access. -
sam over 6 yearsHow do you decode and process data from other fields that will be submitted together with the images?
-
Umair Ahmed over 6 years@sam There is no need to decode the other fields. They are not getting encoded in the first place, only the file gets encoded.
-
sam over 6 yearsCan you share some sample code for the html ,javascript and how to retrieve in laravel php.
-
bungdito about 6 yearsthe upload process with that html and javascript seems works to me, but not work when I want to process on server side script.. i dont understand how to decode using base64_decode() on codeigniter controller to upload file :D
-
bungdito about 6 yearsi used file_put_contents() to save decoded image file, it's works.. but the file can't open/view
-
Umair Ahmed about 6 years@bungdito Sorry, can't say anything about CI. I haven't done file handling in it.
-
Grey Li almost 6 yearsIs it possible to submit the form after
processQueue()
call? I try to usesubmit()
orclick()
, both not work. -
cyril over 5 yearswhen autoProcessQueue= false no events are fired
-
Varan Sinayee over 5 years@Sato on click event of submit button you can check the length of accepted files on dropzone by using galleryfile.getAcceptedFiles().length and if there is no file uploaded you should submit your form.
-
Varan Sinayee over 5 years@EdwardChopuryan This is not related to the method of submiting data by dropzone. Likely the problem is on your "naming convention" of input tags on your platform such as ASP.Net MVC.
-
Emiel Bruijntjes over 5 years+1 This seems to be the only working solution. Instead of doing formData.append one by one, you can also do
$(":input[name]", $("form")).each(function () { formData.append(this.name, $(':input[name=' + this.name + ']', $("form")).val()); });
(sorry I don't know how to put linebreaks here) -
AleXzpm over 5 yearsthis will only work for one image, if you try to add more the $('#file').val(content); will override the input and only the last image will be sent to the server, how can I change this to send multiple images?
-
Umair Ahmed over 5 years@AleXzpm Sorry, that was the first and last time I used Dropzone, can't help you for the time being.
-
AleXzpm over 5 yearsIf you want to add mutiple images you have to remove the html file input and add it quing js for each image $('#fileUpload').append('<input hidden name="files[]" value='+content+'/>') where content is the base64 encoded image.
-
Umair Ahmed over 5 years@AleXzpm if you can suggest an edit, please do so, I'll accommodate it. Or you can post a separate answer extending mine.
-
Leoh over 5 yearshow can i append another input file for a single image?
-
zen about 5 yearsI'm trying to use this and it works in bringing the hidden file input field to the form, and when I submit, the post data shows my field
files[]
but it is blank no matter what I do. Any ideas? Doing it in Laravel if it makes any difference. -
zen about 5 yearsThis doesn't submit dropzone images together with other form fields. What you're doing is uploading images normally, saving the image names, and then re-submitting rest of the form fields with image names.
-
Radderz about 5 yearsThere is already an option within dropzone.js to set the autoDiscover = false. Setting this option within the document load was too late in the page execution cycle for me.
-
Sem over 4 yearsNot sure why, but I have to use $('#myDropzone').dropzone({...}) instead of Dropzone.options.myDropzone. Other than that, worked nicely.
-
Antony over 4 yearsI like this answer - but it would assume that fieldname and value have been populated. This is triggered on the upload which may occur at a separate time to the form submission. In otherwords you can't assume that when sending the image the form is filled out.
-
codepushr over 4 yearsThis won't work reliably, as the input fields value has a browser capped max size. In my case the uploaded file is capped at 384kb, due to the base64 string not fitting completely into the value.
-
Ingus about 4 yearsPerfect! This is the closest i need!
-
Ingus almost 4 yearsHello! Why does selected file does upload but if file is dropped then not (error 4)?
-
Bodo over 3 years@doflamingo I found it better to redirect/show confirmation inside the completemultiple event handler. Doing so in the success handler made it execute multiple times (for each file attached), which sometimes even interrupted the form upload altogether.
-
ucMedia over 3 yearsWorks like charm!
-
Shehroz Altaf over 3 yearsIt is working, But I am uploading 3 images, it is only sending 2 images on the backend. I have changed this below code: maxFiles: 10, uploadMultiple: true, Why it is sending only 2 images?
-
Antony over 3 yearsI would try with an alternative image and see if its a problem with the files. Alternatively does your PHP/ASP etc give you any errors? It could be the image is too big, not enough disc space, server limits/settings etc.
-
Shehroz Altaf over 3 yearsNo. My PHP has no error. It is uploading images correctly. However, I got the solution. I changed below lines: url: myURL uploadMultiple: true, parallelUploads: 25, maxFiles: 25, autoProcessQueue: false, addRemoveLinks: true,
-
aross about 3 yearsThis is the only answer that works with a plain form submit, so does not require JS to handle the form submit.
-
Rich about 3 yearsI find your explanations very interesting. I can't get the elements to go to the processing page. I think it has to do with sessions. Could you give an example of the php processing page or indicate why my _FILE and _POST elements are not resolving.
-
Antony about 3 yearsJust post to a page that does <?php print_r($_FILES); print_r($_POST); ?> and analyse it through the Browser console > Networking tab (thats what its called in Chrome) and see what outputs.
-
Santosh Dangare over 2 yearsI got exactly what I'am looking for, thank you @Satindersingh
-
Hodorogea Alexandru about 2 yearsI get
Uncaught ReferenceError: dzClosure is not defined
when using this :( Does anyone know how I could fix that? -
mending3 about 2 yearsis this ajax request?