I'm using for the first time dropzone.js inside another form...so as two forms can't be nested, I removed dropzone's form:
html snippet:
<form id="addproduct" name="addproduct" action="receiveAddForm" method="post" enctype="multipart/form-data">
<fieldset class="form-horizontal">
<div class="form-group">
<div class="col-sm-2">
<small class="text-navy"><b>* Campos Obligatorios</b></small>
</div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Nombre (Modelo) *:</label>
<div class="col-sm-10"><input name="name" type="text" class="form-control"></div>
</div>
</fieldset>
<div class="dropzone dropzone-previews" id="my-awesome-dropzone"></div>
</form>
js snippet:
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 3,
addRemoveLinks: true,
maxFilesize: 10,
url: 'receiveAddForm',
init: function() {
var myDropzone = this;
$("#submit_form").click(function (e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
this.on("sendingmultiple", function() {
});
this.on("successmultiple", function(files, response) {
});
this.on("errormultiple", function(files, response) {
});
this.on("maxfilesexceeded", function(file){
// alert("No more files please!");
});
this.on("uploadprogress", function(file, progress) {
console.log("File progress", progress);
});
}
}
so in server side I'm getting this after echoing $_FILES:
array (size=1)
'files' =>
array (size=5)
'name' => string '' (length=0)
'type' => string '' (length=0)
'tmp_name' => string '' (length=0)
'error' => int 4
'size' => int 0
what seems to be the problem here? my php.ini is set to 1000MB in upload max file size, memory limit and so on... any help would be appreciatted!
The 'error' => int 4 means that no file has been uploaded, i think this is because you are submitting the form like if it was a regular form, if you want to include dropzone inside a regular form i don't think you can submit the form the regular way and attach to it the files dropped in the dropzone element, or at least there is no simple way to do it, one solution could be to encode the file in base64 and then add the encoded string to an input to send.
But an easy one I think is to send the form using dropzone and append the input values to the request using javascript, here generic example.
html:
<form id="addproduct">
<label>Input 1: </label>
<input type="text" name="input1">
<label>Input 2: </label>
<input type="text" name="input2">
<div id="myAwesomeDropzone" class="dropzone"></div>
</form>
<button type="button" id="submit_form">Submit</button>
js:
Dropzone.options.myAwesomeDropzone = {
url: 'receiveAddForm',
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 3,
maxFiles: 3,
init: function () {
var myDropzone = this;
$('#submit_form').on("click", function() {
myDropzone.processQueue();
});
this.on("sending", function(file, xhr, formData){
$('#addproduct').find('input').each(function() {
formData.append( $(this).attr('name'), $(this).val() );
});
});
this.on("success", function(file, response) {
console.log(response);
});
this.on("completemultiple", function(files) {
// Here goes what you want to do when the upload is done
// Redirect, reload , load content ......
});
},
};
receiveAddForm (php):
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
echo "RECEIVED ON SERVER: \n";
print_r($_FILES);
print_r($_POST);
}
The server file just prints the data received on the server, so you can see it in browsers console. I omitted bootstrap classes and elements only to show the relevant part, but you cand add them no problem.
to have a dropzone inside another form you can put a div in the form with class="dropzone" and convert it to dropzone element like this:
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("#my-awesome-dropzone", {
autoProcessQueue: false,
url: "receiveAddForm",
// other options
});
then you can call the events like this:
myDropzone.on("addedfile", function(file) {
console.log("File added:", file.name);
});
jsfiddle with your form :
fiddle
Related
I have a model called Masseur and another model MasseurImage connected with a belongsTo() relationship. I also have a form with some basic inputs and Dropzone image upload integrated. The idea is when the "Create new masseur" form is submitted, it creates a new Masseur entry in the db, and creates many MasseurImage entries (based on how many images has been added into the dropzone field).
Everything works fine, except the Masseur model is saved twice in the database after the form is submitted.
View
<form method="post" id="etCreateMasseurForm" action="{{ route('masseur.add') }}" name="etCreateMasseurForm" enctype="multipart/form-data">
#csrf
<input type="hidden" name="masseur_id" id="masseur_id">
<div class="form-group mb-3">
<label class="form-label" for="nickname">Becenév</label>
<input class="form-control" type="text" name="nickname" id="nickname" required>
</div>
<div class="form-group mb-3">
<label class="form-label" for="name">Név</label>
<input class="form-control" type="text" name="name" id="name" required>
</div>
<div id="dropzoneDragArea" class="dropzone dz-default dz-message dropzoneDragArea form-control"></div>
</form>
Controller
public function store(Request $request)
{
$masseur = Masseur::create($request->all());
if ($request->hasFile('file')) {
foreach ($request->file('file') as $file) {
$filename = $file->store('public/files/'.$masseur->id);
MasseurImage::create([
'masseur_id' => $masseur->id,
'filename' => $filename
]);
}
}
return response()->json(['status' => "success", 'masseur_id'=> $masseur->id]);
}
Javascript
Dropzone.autoDiscover = false;
let token = $('meta[name="csrf-token"]').attr('content');
$(function () {
var myDropzone = new Dropzone("div#dropzoneDragArea", {
paramName: "file",
url: "{{ route('masseur.add') }}",
addRemoveLinks: true,
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
params: {
_token: token
},
init: function () {
var myDropzone = this;
$("form[name='etCreateMasseurForm']").submit(function (event) {
event.preventDefault();
URL = $("#etCreateMasseurForm").attr('action');
formData = $('#etCreateMasseurForm').serialize();
$.ajax({
type: 'POST',
url: URL,
data: formData,
success: function (result) {
if (result.status == "success") {
var masseur_id = result.masseur_id;
$("#masseur_id").val(masseur_id);
myDropzone.processQueue();
} else {
console.log("error");
}
}
});
});
this.on('sending', function (file, xhr, formData) {
let masseur_id = document.getElementById('masseur_id').value;
formData.append('masseur_id', masseur_id);
});
this.on("success", function (file, response) {
window.location.href = "/";
});
this.on("queuecomplete", function () {
});
}
});
});
Routes
Route::post('store-masseur', [MasseurController::class, 'store'])->name('masseur.add');
i have multiple input, textarea and select i need multiple image upload so i try dropzone js and in controller request there is no file
i use autoProcessQueue: false and its not working but if i don't use it upload but i don't get data in request file
Problem is how can i get request file from dropzone
this is dropzone script
<script>
Dropzone.options.dropzone =
{
// The configuration we've talked about above
url: "{{ route('product.store') }}",
headers: {
'x-csrf-token': "{{ csrf_token() }}",
},
// autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
// The setting up of the dropzone
init: function() {
var myDropzone = this;
var formData = new FormData();
// First change the button to actually tell Dropzone to process the queue.
$("#prodcutCreate").click(function (e){
// Make sure that the form isn't actually being sent.
var formData = new FormData(this);
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.
// formData.append("name", $("#name").val());
// formData.append("slug", $("#slug").val());
// formData.append("description", $("#description").val());
// formData.append("ideal_for", $("#ideal_for").val());
// formData.append("main_ingredients", $("#main_ingredients").val());
// formData.append("gender_id", $("#gender_id").val());
// formData.append("brand_id", $("#brand_id").val());
// formData.append("categories", $("#categories").val());
});
this.on("successmultiple", function(files, response) {
// Gets triggered when the files have successfully been sent.
// Redirect user or notify of success.
console.log('success');
console.log(files);
console.log(response);
});
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
console.log(false);
console.log(files);
console.log(response);
});
}
}
this is controller i dd the request but no file
public function store(Request $request){dd($request); }
this is form i have other input fileds too
<form method="POST" action="{{ route('product.store') }}" enctype="multipart/form-data">
<div class="col-span-4 dropzone" id="dropzone"></div>
this is from $request
files: Symfony\Component\HttpFoundation\FileBag
{#46
#parameters: []
}
thanks
I'm still a noob at DropzoneJs, but I'm slowly evolving. I have a problem. I have two dropzones that work perfectly, they upload the images and register in the bank. The problem is that I wanted to send both dropzone data at the same time but it only sends one at a time, so in the database it registers one after registering the other. Is there any way to send the data of the two dropzones at the same time I want to register the data on the same bank line.
My HTML:
<form action="upload.php" class="form" method="POST" enctype="multipart/form-data">
<div>
<br>
<div class="dropzone" id="kt_dropzonejs_example_1">
<div class="dz-message needsclick">
<input type="hidden" value="1" name="id_product" id="id_product" />
<div>
<h3>Clique ou arraste para selecionar</h3>
<span>Nota Fiscal</span>
</div>
</div>
</div>
<br>
<div class="dropzone" id="kt_dropzonejs_example_2">
<div class="dz-message needsclick">
<div>
<h3>Clique ou arraste para selecionar</h3>
<span>Nota Fiscal</span>
</div>
</div>
</div>
<br>
</div>
</form>
<br>
<button type="submit" id="button">Submit</button>
Codigo Javascript:
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("#kt_dropzonejs_example_1", {
autoProcessQueue: false,
url: "upload.php", // Set the url for your upload script location
paramName: function() {
return 'files[]';
},
autoDiscover: false,
maxFiles: 10,
acceptedFiles: ".png,.jpg,.pdf,.jpeg",
uploadMultiple: true,
parallelUploads: 10,
maxFilesize: 10, // MB
addRemoveLinks: true,
dictRemoveFile: 'Remover Arquivo',
init: function() {
this.on("removedfile", function(file) {
alert("Deletar o arquivo " + file.name + " ?");
});
this.on('success', (file) => {
file._removeLink.remove();
delete file._removeLink;
});
this.on("sendingmultiple", function(data, xhr, formData) {
formData.append("id_product", jQuery("#id_product").val());
});
}
});
Dropzone.autoDiscover = false;
var myDropzone2 = new Dropzone("#kt_dropzonejs_example_2", {
autoProcessQueue: false,
url: "upload.php", // Set the url for your upload script location
paramName: function() {
return 'pages[]';
},
autoDiscover: false,
maxFiles: 10,
acceptedFiles: ".png,.jpg,.pdf,.jpeg",
uploadMultiple: true,
parallelUploads: 10,
maxFilesize: 10, // MB
addRemoveLinks: true,
dictRemoveFile: 'Remover Arquivo',
init: function() {
this.on("removedfile", function(file) {
alert("Deletar o arquivo " + file.name + " ?");
});
this.on('success', (file) => {
file._removeLink.remove();
delete file._removeLink;
});
}
});
//Here I send the dropzone data
$("#button").click(function(e) {
e.preventDefault();
myDropzone.processQueue();
myDropzone2.processQueue();
});
I'm trying to add an id attribute to each file uploaded in Dropzone.js, So I can sort it later on.
This is my code:
Dropzone.options.pictureDropzone = {
paramName: "file",
addRemoveLinks: true,
init: function() {
this.on("success", function(file, response) {
file.serverId = response.id;
$(file.previewTemplate).find('.dz-preview').attr('id', "document-" + file.serverId);
});
}
};
The line
$(file.previewTemplate).find('.dz-preview').attr('id', "document-" + file.serverId);
Should add the id, but it does nothing.
Tried it with prop() too.
If I choose a different element, it does work fine. for example, this works for .dz-details
$(file.previewTemplate).find('.dz-details').attr('id', "document-" + file.serverId);
But I cannot seem to find a way to add it to the dz-preview element.
The HTML structure looks like that:
<div class="dz-preview dz-processing dz-image-preview dz-success">
<div class="dz-details"> ... </div>
<div class="dz-progress"> ... </div>
<div class="dz-success-mark"> ... </div>
</div>
Thank you for the help :)
I know this is old but if anyone is still looking for the answer: -
this.on("success", function(file, response) {
file.previewElement.id = response.id;
});
Cast the previewElement into jQuery object and perform any action.
this.on("success", function(file, response) {
$(file.previewElement).attr("id", response.id);
});
this.on("success", function(file, response) {
file.serverId = response.id;
$(".dz-preview:last-child").attr('id', "document-" + file.serverId);
});
I had similar problem but tried it through declaring a variable in javascript ,following is code :
$("#fileUpload${dropdown}").dropzone(
{
url : "uploadAdditionalFile?name="+$("#fileUpload${dropdown} div:first-child").prop('id'),
addRemoveLinks : true,
maxFiles : 1,
init : function() {
var imageId = $("#fileUpload${dropdown} div:first-child").prop('id');
this.on("maxfilesexceeded",
function(file) {
alert("Only one file can be uploaded at a time");
this.removeFile(file);
});
this.on("addedfile",
function(file) {
switch (file.type) {
case 'application/pdf':
this.emit("thumbnail",file,"/sbms/static/img/pdf.png");
break;
case 'application/msword':
this.emit("thumbnail",file,"/sbms/static/img/word.png");
break;
}
}
);
this.on('removedfile', function(file){
$.ajax({
type : "GET",
url : "removeAdditionalMediaPreviewForm?id="+imageId,
dataType : "json",
async : false,
success : function(response) {
if (response.status == 'SUCCESS') {
alert("File removed successfully.")
}else {
alert("File not removed successfully.")
}
}
});
});
},
success : function(file,response) {
var imgName = response;
file.previewElement.classList.add("dz-success");
console.log("Successfully uploaded :"+ imgName);
},
error : function(file,response, xhr) {
alert("Unable to upload file. Please check if it is a valid doc or pdf file.");
this.removeFile(file);
}
});
imageId is a variable which stores the id and is used later on while file remove.
This will fail spectacularly if the user drops multiple files.(Szczepan Hołyszewski Dec 17 '15 at 18:45);
BryanFoong answer won't fail if you set the option uploadMultiple: false. Which is set so by default. In this case Dropzone sends separate request to the server for each file. Therefore "success" event triggers for each individual file.
In case the uploadMultiple: true. Dropzone will send single request to server for all files. And "success" event will trigger once. And following code will handle that.
YourDropzoneInstance.on("success", function(file, response) {
response.files.forEach(function(file) {
file.previewTemplate.id = file.id;
})
})
Again you need to return from server array of files.
In PHP it will look like
function yourFileUploadHandler() {
...
// your server file upload implementation
$response = [
"files" => [
["id" = 1, ...],
["id" = 2, ...],
...
],
];
return json_decode($response);
}
I am trying to implement ajax file upload via the HTML5 File API. It's based on Afzaal Ahmad Zeeshan's answer to this question.
I've basically copied the entire code that he wrote, but can't get it to work.
The main aim here is to be able to upload .xls and .xlsx files to the server to work with them later with PHPExcel.
Here's my HTML:
<form class="form-uploadXLS" method="post" action="php/uploadXLS.php" enctype="multipart/form-data">
<div class="form-group">
<div class="col-md-12">
<input type="file" name="xls" class="xls" />
</div>
</div>
<input type="button" value="Upload" class="btn-uploadXLS" />
</form>
<progress></progress>
And here are the jQuery event handlers, just like in the above mentioned answer:
File input onChange event:
$('.xls').on('change', function () {
var file = this.files[0];
var fileName = file.name;
var fileType = file.type;
var fileSize = file.size;
console.log("file name: " + fileName + ", type: " + fileType + ", size: " + fileSize);
});
Upload button's onClick event:
$('.btn-uploadXLS').on('click', function (event) {
event.preventDefault();
console.log("Upload button clicked");
var formData = new FormData($('.form-uploadXLS')[0]);
$.ajax({
url: 'php/uploadXLS.php', //Server script to process data
type: 'POST',
xhr: function () { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // Check if upload property exists
myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // For handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: function (stuff) {
console.log("BeforeSend");
console.log(stuff);
},
success: function (data) {
console.log("Success!");
console.log(data);
},
error: function (error) {
console.log("Error!");
console.log(error);
},
// Form data
data: formData,
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
});
});
Edit starts here:
And finally here's my PHP code that prints out the $_FILES array:
if(!empty($_FILES['xls'])) {
echo '<pre>',print_r($_FILES,1),'</pre>';
}
else {
die('POST ÜRES');
}
And here's the result:
Array
(
[xls] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
)
For some reason I can't access the error messages, it only contains the number 4.
What am I doing wrong?
For files you need
$_FILES['xls'] not $_POST
Read Handling file uploads
To get more info just print array
echo '<pre>',print_r($_FILES,1),'</pre>'
Read php - file upload
Ajax File Upload with PHP, HTML5 File API and jQuery