I have an issue using the JQuery-File-Upload plugin. I am using the plugin directly and not through the author's provided html example pages. Basically I have a form with some inputs
one of which is a file input. The first upload works fine but when I attempt a second upload both files are sent (the first one for the second time) when it should only be the second one.
Example:
File 1 is selected.
File 1 is uploaded.
Success.
Using jquery I reset the form with $(FORM_SELECTOR).trigger('reset')
File 2 is selected.
File 1 and file 2 are BOTH uploaded.
Problem.
Now I have two copies of file 1. This is not what I want.
Obviously there isn't much point of using an ajax form upload if it only works once so I assume that there is something I am missing.
Is there a way to reset the file queue?
When examining the data.files object I can see that the files are there after the form
is reset. What can I do to sync the plugin with the input or clear out the data.files.
If I manually clear out the data.files array (via pop or data.files = []) attempting a
second upload does not work.
I init the upload form like this:
$('#file-upload-form').fileupload({
url: 'uploads/upload',
type: 'POST',
dataType: 'json',
multipart: true,
dropZone: null,
formAcceptCharset: 'utf-8',
autoUpload: true,
add: function (e, data) {
fileUploadData = data;
$("#upload-file-btn").click(function () {
data.submit()
.success(function (e, status, data) {
console.log("success response from post", status, data);
var i = '<input id="file-select-input" name="files[]" multiple/>';
$('#file-select-input').replaceWith(i);
})
});
}
});
I have a custom .add event handler, in which I have called .off("click") on my button:
add: function (e, data) {
$('#btnstartupload').off("click");
data.context = $('#btnstartupload')
.click(function () {
data.submit();
$(".fileinput-button").hide();
});
}
I had the same problem and the only way I've managed to solve that was to check in the submit callback if the file was already uploaded. I just check if the file name is included in the array fileNames which I push the current file name before the submission and checks on the next time if the next one is present on the array and if so cancel the submission.
var fileNames = new Array();
$('#uploadfile').fileupload({
submit: function(e, data) ->
var fileName = data.files[0].name;
if ($.inArray(fileName, fileNames) === -1)
fileNames.push(fileName);
else
return false;
});
You can reset inputs quite easy.
If that does not work for you, you might store the file somwhere.
DEMO
$("button#1").click(function(){
//check file
alert($("input").val());
return false;
});
$("button#2").click(function(){
//reset form
$("form")[0].reset();
return false;
});
$("button#3").click(function(){
//replace input
$("input").replaceWith($('<input type="file"/>'));
return false;
});
I ran into the same problem. It's puzzling why the library re-sends previously uploaded files. I tried to destroy it, re-initialize it and clear/reset the actual file input field, but none of them worked.
The solution I came up with is to keep track of all upload attempts by storing file names in an array and checking in the "send" callback if a file has been already uploaded.
Callback:
send: function (e, data) {
var file = data.files[0];
// if we already attempted to upload a file with the same file name
// do not send it in order to avoid duplicates
if (existsInAttemptedUploads(file.name)) {
return false;
}
},
Helper methods:
// list of file names that a user attempted to upload
var attemptedUploads = [];
// adds a file name to the list of attempted uploads
function addAttemptedUpload(fileName) {
attemptedUploads.push(fileName);
};
// removes a given file name from the list of attempted uploads
function removeAttemptedUpload(fileName) {
var index = $.inArray(fileName, attemptedUploads);
if (index > -1) {
attemptedUploads.splice(index, 1);
}
};
// checks if a given file name is in the list of attempted uploads
function existsInAttemptedUploads(fileName) {
var result = $.inArray(fileName, attemptedUploads);
if (result == -1) {
return false;
}
return true
};
Make sure to update the list of attemptedUploads in your "done" and "fail" callbacks and remove a file from the list if it was removed. For example:
done: function (e, data) {
var id = e.target.id;
// List all uploaded files
$.each(data.result.files[0], function (index, file) {
// add the current file name to the list of attempted file names
addAttemptedUpload(file.origFileName);
$('#uploadedFiles').append('<li id="' + file.id + '" data-orig-filename="' + file.origFileName + '">' + file.fileName + ' <a class="removeFile" href="<?php echo $deleteUrl; ?>/' + file.id + '">' + ' Remove</a></li>');
});
},
My code like that, when clicking the Remove link into the multiple file from JSP page, It's OK for IE11, Chrome and Firefox.
function removeFileLink(id) {
var fileName = document.getElementById("import_file_" + id).value.replace(/^.*[\\\/]/, '');
var objFiles = document.getElementsByName("import_fileList");
for(var i=0; i<objFiles.length; i++){
if(objFiles[i].value.replace(/^.*[\\\/]/, '') == fileName) {
$(objFiles[i]).remove();
}
}
document.getElementById("import_form").enctype="multipart/form-data";
document.getElementById("import_form").submit();
return false;
}
Related
I have a simple dropbox that uploads files manually when a button is clicked:
var dropzone = $("#dropzone-form").dropzone({
autoProcessQueue: false,
addRemoveLinks: true,
paramName: "fotos",
url: url,
uploadMultiple: true,
init: function(){
var dropzone_object = this;
$('#btn-guardar').on('click', function(e){
if(checkForm()){
if(dropzone_object.files.length > 0){
dropzone_object.processQueue();
}else{
sendWithoutFiles();
}
}
});
},
sending: function(file, xhr, formData) {
var formValues = $('#form-productos').serializeArray();
$.each(formValues, function(i, obj){
formData.append(obj.name, obj.value);
});
},
success: function(file, response){
},
error: function(file, errorMessage, xhr){
}
});
But I'm having problems when I upload more than one file because I have array inputs inside my form with id form-productos such as this:
<input name="emails[]">
or
<select name="colors[]"></select>
So, for each file that the dropzone queue has, it appends the input again, the inputs that are NOT array inputs have no problem because the value just gets overwritten again, so let's suppose that I have the following inputs (NOTE THE VALUES):
<input name="emails[]" value="email1">
<input name="emails[]" value="email2">
And also, let's suppose that I have 2 files in the queue, when I press the button and the data is being sent to PHP, I get the following when I print "$request->emails":
array(
'email1',
'email2', //After this, since I uploaded two files, I get the same values again:
'email1',
'email2'
)
Reading the dropzone documentation clearly states that this is the correct behaviour:
sending: Called just before each file is sent. Gets the xhr object and
the formData objects as second and third parameters, so you can modify
them (for example to add a CSRF token) or add additional data.
So, the problem is on my side, what can I do to prevent this when appending to formData?
I solved the issue easily replacing the send event with sendingmultiple, this event should be used in most cases when the uploadMultiple option is set to true:
sendingmultiple: function(files, xhr, formData) {
var formValues = $('#form-productos').serializeArray();
$.each(formValues, function(i, obj){
formData.append(obj.name, obj.value);
});
},
The difference is that this event receives a file array as first parameter, in this way, the process inside the event is only done once.
I am using the Dropzone JS plugin to upload and manage images on my server. Everything works great, but now I need to force the user to keep at least one image for the product. That means that if the users wants to change the images they need to upload a new one image before they delete the old one.
I can manage it on the server side, but I can't figure out a way to retain the thumbnail visible and notify the user they are not allowed to delete the last one. Just keeping the image on the server without telling the users whats going on will result on a bad UX.
Here is my code
$("div#myId").dropzone({
url: "/stores/sell_upload/",
maxFiles: 4,
acceptedFiles: "image/*",
addRemoveLinks: true,
renameFile: function(file) {
let newName = file.name.replace("." + file.name.split(".").pop(), "") + "-" + new Date().getTime() + "." + file.name.split(".").pop();
return newName;
},
removedfile: function(file) {
$.ajax({
type: "POST",
url: "/stores/sell_upload/",
data: {
name: file.name,
action: "delete"
}
});
var _ref;
return (_ref = file.previewElement) != null ? _ref.parentNode.removeChild(file.previewElement) : void 0;
}
});
So, Wouldn't it be easier if you validated the files in the action of the button to save? I mean, the dropzone area can be empty but you in your button action validate that it has to be at least one file in the area to be saved.
I'm making a step by step form that stores session variables as you follow the steps.
On one step I have a file upload that previews the image and shows an upload button, which when pressed calls a php script that needs to modify a $_SESSION variable, as well as echo the path to the uploaded file.
When I test it in my debugger without require_once('config.php'), it works exactly as I anticipate, showing the image and it's filename, however, for some reason when I include the config file, when I iterate through it in my debugger, it appears to run the php script twice, it correctly updates the session variable, but the filename isn't echoed anymore and the data is lost before it reaches the frontend.
I can't tell if the mistake is in the config.php file, or in the AJAX call, or maybe somewhere else where I'm missing.
The markup ('step4.php'):
<form method="post" action="step5.php">
<span id="newfile">
<input type="file" name="uploaded_file" id="imageupload" accept=".jpg, .jpeg, .png">
<img alt="Preview Loading..." id="imagepreview">
</span>
<!-- The submit button is elsewhere before the end of the form, it acts as a next button -->
</form>
The javascript function:
$(document).on('click', '#uploadbutton', function(e) {
e.preventDefault();
//Grab upload elements and and file
var uploadbutton = this;
var uploader = document.getElementById('imageupload');
var file = document.getElementById('imageupload').files[0];
//Hide the upload elements
uploadbutton.parentNode.removeChild(uploadbutton);
uploader.parentNode.removeChild(uploader);
//Make the form and pass it to server
var formData = new FormData();
formData.append('file', file); //$_FILES['file']
$.ajax({
url: 'uploadfile.php',
type: 'POST',
data: formData,
processData: false,
contentType: false
})
.done(function(data) {//Data is the relative path to the file
//Hide the old content
document.getElementById('newfile').innerHTML = '';
//Show the new image
var text = document.createTextNode('Uploaded File: '+data.replace('temp/', '', data));
var br = document.createElement("br");
var imgElement = document.createElement("IMG");
imgElement.setAttribute('src', data);
document.getElementById('newfile').appendChild(text);
document.getElementById('newfile').appendChild(br);
document.getElementById('newfile').appendChild(imgElement);
})
.fail(function() {
alert("Error uploading the file. Hit refresh and try again.");
});
});
'uploadfile.php': (the one that my debugger shows gets executed twice...)
<?php
//require_once('config.php'); //THE PROBLEM?
if($_FILES) {
//Get the uploaded file information
$name_of_uploaded_file = $_FILES['file']['name'];
//Actually upload the file to the server!
$upload_folder = 'temp/'; //Make a file named temp
$path_of_uploaded_file = $upload_folder.$name_of_uploaded_file;
$tmp_path = $_FILES["file"]["tmp_name"];
if(is_uploaded_file($tmp_path)) {
copy($tmp_path,$path_of_uploaded_file);
$_SESSION['step4filepath'] = $path_of_uploaded_file;
echo $path_of_uploaded_file;
}
}
?>
'config.php': the one that screws stuff up when it's included
<?php
session_start();
//Initialize session data
if(empty($_SESSION)) {
if(!isset($_SESSION['step4filepath'])) {
$_SESSION['step4filepath'] = '';
}
}
//Update session data
if($_SERVER['REQUEST_METHOD'] === 'POST') {
if($_SESSION['currentPage'] == 4) {
//input for step 4, we just want filename if they submit the form
$_SESSION['step4filepath'] = $_POST['step4filepath'];
}
//Enable us to hit the back button!
header("Location: " . $_SERVER['REQUEST_URI']);
}
?>
Totally lost on this.
May be this? Why that line is there on your config file?
header("Location: " . $_SERVER['REQUEST_URI']);
It looks like config.php is replacing the value of $_SESSION['step4filepath'] with $_POST['step4filepath'], rather than leaving it as $path_of_uploaded_file.
EDIT
As mentioned elsewhere, header() will be causing a reload. My answer is irrelevant as config.php is called before the var is set.
Solution 1
Replace
$(document).on('click', '#uploadbutton', function(e) {
To
$(document).off('click').on('click', '#uploadbutton', function(e) {
Solution 2: See below sample code
$(document).on("click", "#someID", function(e) {
$(this).attr("disabled","disabled");
// Disabling the input stops the event from firing multiple times.
var targetObj = $(this);
// targetObj can be used within the $.POST function, not $(this)
var myVariable = "Hello world";
$.post("/DoSomethingAJAXY.php", { variable1: myVariable },
function(data, status){
if (status == "success") {
// Do something
}
$(targetObj).removeAttr("disabled");
// Re-enable the event input trigger
});
}
I have an issue trying to remove the files which I have passed dropzone.js after calling the database.
When I navigate to the page and upload a new image and then remove it without refreshing the page it all works as expected.
Below is my current upload method
myDropzone.on("success", function (file, response) {
console.log(response);
file.serverId = response;
});
This is what is inside the response after doing console.log(response);
Object { UniqueId="evgopvdjfs1w9sos3jt5"}
Which is correct.
Now when I press F5 and refresh the page I populate dropzone with the following snippet which returns me the image that I've just uploaded.
$.getJSON("/Person/GetPreviews/").done(function (data) {
if (data.Data != '') {
$.each(data.Data, function (index, item) {
var UniqueId = item.ImageName;
var mockFile = {
name: item.ImageName,
serverId: UniqueId // This is what I need to delete the image
};
console.log(mockFile);
// Call the default addedfile event handler
myDropzone.emit("addedfile", mockFile);
// And optionally show the thumbnail of the file:
myDropzone.emit("thumbnail", mockFile, item.ImageUrl);
myDropzone.files.push(mockFile);
});
}
});
Now when I do console.log(mockFile); the below is shown, again this is correct.
Object { name="evgopvdjfs1w9sos3jt5", UniqueId="evgopvdjfs1w9sos3jt5"}
Now when it comes to removing the file this is my current delete function
removedfile: function (file) {
console.log(file);
$.ajax({
type: 'POST',
url: '#Url.Action("DeleteUploadedFile", "Person", new {userId= #Model.UserId})',
data: "id=" + file.serverId['UniqueId'],
dataType: 'html',
});
var ref;
return (ref = file.previewElement) != null ? ref.parentNode.removeChild(file.previewElement) : void 0;
},
Now when I press remove file on the pre populated image from the database, it throws an error on
data: "id=" + file.serverId['UniqueId'],
saying its underfined, I personally cannot see how because both console.logs show the UniqueId it makes me wonder if I'm missing something when I'm pre populating dropzone with the images?
As you can see I have a console.log(file); in the delete function which when hit shows the following
Object { name="evgopvdjfs1w9sos3jt5", UniqueId="evgopvdjfs1w9sos3jt5"}
Can anyone see whats wrong?
So this question is a bit old. I came across it and also found this answer, which helped me:
http://www.stackoverflow.com/questions/24445724/add-existing-image-files-in-dropzone
This particular question was answered here and just points out a mix-up between serverId and UniqueId:
https://github.com/enyo/dropzone/issues/844
im using jquery validate and I would like to know if there is a way to check the validation only for one field of my form before calling the validation method of all of its fields:
var validator = $("#form").validate();
validator.form()
I want to do this because when the user uploads a file this one is uploaded to the server automatically, so i would like to validate the file extension before uploading the file to the server.
So i would like to have something like:
In my HTML:
<input type="file" id="linkIcon" name="linkIcon" data-url="/server/upload" required extension="jpg">
And in my JS:
$('input[type=file]').change(function(e){
if($this).valid()){
//Do stuff...
}
});
Update: Ok that worked well, but now i need to abort the file upload
this is what i have Im using jquery fileupload
$(function () {
$('#linkIcon').fileupload({
dataType: 'json',
beforeSend: function(){
if(!$('#linkIcon').valid()){
alert("invalid extension");
$(this)[0].abort();
}
},
done: function (e, data) {
//SUCCESS
alert("file uploaded");
},
replaceFileInput: false
});
});
You can check the extension of the file before calling the .valid() function.
jsFiddle here
$('input[type=file]').change(function (e) {
var fileName = $(this).val().replace(/^.*[\\\/]/, '');//Gets the file name
var isCorrectExtension = false;
if (fileName != null) {
var extension = fileName.substr((fileName.lastIndexOf('.') + 1)).toLowerCase();
if (extension === 'jpg' || extension === 'jpeg')
isCorrectExtension = true;
}
if (isCorrectExtension) {
//Do stuff...
}
});