0
Dropzone.options.dropzone = {
    uploadMultiple: false,
    maxFiles: {{ imagecount }},
    maxFilesize: 2, // MB
    dictFileTooBig: "That image is too large. We only allow 2MB or smaller.",
    acceptedFiles: ".jpeg, .jpg",
    init: function () {
        this.on("success", function(file, response) {
            $('.uploaded-photos').append('<div><img src="' + response.link + '"height="150" class="photo" id="' + response.id + '"/><span class="delete-photo">Delete</span></div>');
            $('.uploaded-photos').justifiedGallery('norewind')
            this.removeFile(file);

            var grabNewCount = parseInt($('.recordcount').text(), 10)
            $('.recordcount span').text(grabNewCount += 1);
            }); 
    }
};

I'm trying to dynamically update the MaxFiles property each time a new image is uploaded/deleted.

As you can see, I'm passing {{ imagecount }} from my server when the page loads. This is just a check to see how many images have been uploaded for the user and thus a calculation for how many they have left to upload. On first page load, this works.

The problem seems to arise when I delete an image which I'm using AJAX to do. I can't seem to get that maxFiles value to update. If I allow 10 images initially and a user has 5 currently uploaded and deletes one, then the new maxFiles value should now be 6, but nothing I do seems to have an effect on updating that value dynamically. Here's what I have for my delete code:

$('.delete-photo').click(function() {
    $(this).text('') // remove "delete" text from button
    $(this).html('<i class="fa fa-spinner fa-spin"></i>') // add spinning icon to indicate "working"

    var csrf = $('[name=csrfmiddlewaretoken]').val();
    $.ajax({
        context: this,
        type: "POST",
        url: '/delete-photo/',
        data: {'csrfmiddlewaretoken': csrf, 'id': $(this).parent().attr('id') },
        dataType: "json",
        timeout: 10000,
        cache: false,
        success: function(data, textStatus, XMLHttpRequest){
            var image = $(this).parent();
            $(image).fadeOut(800, function() {
                $(this).remove();
                $('.uploaded-photos').justifiedGallery()
            });
            Dropzone.options.dropzone.maxFiles = Dropzone.options.dropzone.maxFiles + 1;
            var grabNewCount = parseInt($('.recordcount').text(), 10)
            $('.recordcount span').text(grabNewCount -= 1);
                  }
    });
});

So you can see that I've got Dropzone.options.dropzone.maxFiles = Dropzone.options.dropzone.maxFiles + 1; in an attempt to take the current maxFiles value and update the value +1 but that doesn't do anything.

Any ideas?

lexbuckeye
  • 73
  • 2
  • 9

3 Answers3

0

So I got this working by adding a data attribute to the form tag and updating that attribute with a new number each time a new image is deleted or uploaded.

My server side code passes the initial maxfiles ({{imagecount}} tag) count back to the page on load:

<form data-count="{{ imagecount }}">

So my opening dropzone code looks like:

var maxFiles = $('.dropzone').attr('data-count'); Dropzone.options.dropzone = { uploadMultiple: false, maxFiles: maxFiles,

When someone uploads an image via dropzone, inside the .on(success) function I have:

var imagecount = $('.dropzone').attr('data-count'); imagecount = imagecount - 1; $('.dropzone').attr('data-count', imagecount);

And inside of the delete ajax function I have:

var imagecount = $('.dropzone').attr('data-count'); imagecount = imagecount + 1; $('.dropzone').attr('data-count', imagecount);

lexbuckeye
  • 73
  • 2
  • 9
0

After many hours of trials and errors I realized that this maxFiles setting is not working the way most people expect it: it only limits the number of images that can be uploaded from the explorer or drag&drop at once. After reopening the explorer / page reloading more files can be uploaded. I also does not reflect any server failures, like exceeding the file size on file upload.

Moreover, once a dropzone is initialized, the maxFile setting cannot be changed from another script. Thus, when a file is deleted from a gallery outside od the dropzone the maxFile or the inner counter of images cannot be increased.

In my case better solution proved to be blocking upload of the excessive images on the server, in the uploader.php from the <form action="/uploader">

define('MAX_IMAGES', 10);
// Counting how many images already exist in the target directory
$imageCount = 0;
$fi = new FilesystemIterator($targetPath, FilesystemIterator::SKIP_DOTS);
foreach($fi as $fn) {
    $pathInfo = pathinfo($fn);
    $e = $pathInfo['extension'];

    if(in_array($e, array('jpg', 'jpeg', 'png', 'gif'))) {
        $imageCount++;
    }
}

if($imageCount >= MAX_IMAGES) {
    $success = false;
    $error = "Too many images";
    echo '{"name" : "'.$fileName.'", "success": "'.$success.'","extension" : "'.$fileExtension.'","dir_upload:":"'.$targetFolder.'","error":"'.$error.'","imageCount":"'.$imageCount.'"}';
    exit;
}

And then in the success handler of the Dropzone I have:

success: function (file, response) {
    var response_data = jQuery.parseJSON(response);
    if(!response_data.success) {
        errorFiles += 1;
        // Info about the error
        $(file.previewElement).addClass('dz-error').addClass('dz-complete').find('.dz-error-message').text(response_data.error);
    }
}

I hope that helps someone.

gaba
  • 75
  • 1
  • 4
0

The MaxFiles option should not be dynamic, and should not depend on the number of files currently in the Dropzone. It represents the total amount of files that should be allowed to be uploaded in your Dropzone instance.

The correct solution is far more simple: make sure that the mockFiles (provided by the server) include the status of 'Dropzone.ADDED', and 'accepted: true', like this:

var file = {
    name: value.name,
    size: value.size,
    status: Dropzone.ADDED,
    accepted: true
};

myDropzone.emit("addedfile", file);                                
myDropzone.emit("thumbnail", file, value.path);
myDropzone.emit("complete", file);
myDropzone.files.push(file);

Whilst this isn't obvious in the rather sparse documentation, the additional instructions for mockFiles are briefly alluded to here: https://docs.dropzone.dev/configuration/basics/methods?q=mockFiles

But the point is: Include the 'status' and 'accepted' fields as above, for your existing server files to be considered "properly added" and therefore respected by your maxFiles option setting.

No need to write custom functions/logic or form attributes etc.

BSUK
  • 692
  • 1
  • 12
  • 28