Search code examples
fine-uploader

fineuploader - Read file dimensions / Validate by resolution


I would like to validate by file dimensions (resolution).

on the documentation page there is only information regarding file name and size, nothing at all in the docs about dimensions, and I also had no luck on Google.

The purpose of this is that I don't want users to upload low-res photos to my server. Thanks.


Solution

  • As Ray Nicholus had suggested, using the getFile method to get the File object and then use that with the internal instance object qq.ImageValidation to run fineuploader's validation on the file. A promise must be return because this proccess is async.

    function onSubmit(e, id, filename){
        var promise = validateByDimensions(id, [1024, 600]);
        return promise;
    }
    
    function validateByDimensions(id, dimensionsArr){
        var deferred = new $.Deferred(),
            file = uploaderElm.fineUploader('getFile', id),
            imageValidator = new qq.ImageValidation(file, function(){}),
            result = imageValidator.validate({
                minWidth  : dimensionsArr[0],
                minHeight : dimensionsArr[1]
            });
    
        result.done(function(status){
            if( status )
                deferred.reject();
            else
                deferred.resolve();
        });
    
        return deferred.promise();
    }
    



    Remained question:

    Now I wonder how to show the thumbnail of the image that was rejected, while not uploading it to the server, the UI could mark in a different color as an "invalid image", yet the user could see which images we valid and which weren't...

    - Update - (regarding the question above)

    While I do not see how I could have the default behavior of a thumbnail added to the uploader, but not being uploaded, but there is a way to generate thumbnail manually, like so:

    var img = new Image();
    uploaderElm.fineUploader("drawThumbnail", id, img, 200, false);
    

    but then I'll to create an item to be inserted to qq-upload-list myself, and handle it all myself..but still it's not so hard.


    Update (get even more control over dimensions validation)

    You will have to edit (currently) the qq.ImageValidation function to expose outside the private function getWidthHeight. just change that function deceleration to:

    this.getWidthHeight = function(){
    

    Also, it would be even better to change the this.validate function to:

    this.validate = function(limits) {
            var validationEffort = new qq.Promise();
    
            log("Attempting to validate image.");
    
            if (hasNonZeroLimits(limits)) {
                this.getWidthHeight().done(function(dimensions){
                    var failingLimit = getFailingLimit(limits, dimensions);
    
                    if (failingLimit) {
                        validationEffort.failure({ fail:failingLimit, dimensions:dimensions });
                    }
                    else {
                        validationEffort.success({ dimensions:dimensions });
                    }
                }, validationEffort.success);
            }
            else {
                validationEffort.success();
            }
    
            return validationEffort;
        };
    

    So you would get the fail reason, as well as the dimensions. always nice to have more control.

    Now, we could write the custom validation like this:

    function validateFileDimensions(dimensionsLimits){
        var deferred = new $.Deferred(),
            file = this.holderElm.fineUploader('getFile', id),
            imageValidator = new qq.ImageValidation(file, function(){});
    
        imageValidator.getWidthHeight().done(function(dimensions){
            var minWidth = dimensions.width > dimensionsLimits.width,
                minHeight = dimensions.height > dimensionsLimits.height;
    
            // if min-width or min-height satisfied the limits, then approve the image
            if( minWidth || minHeight )
                deferred.resolve();
            else
                deferred.reject();
    
        });
    
        return deferred.promise();
    }
    

    This approach gives much more flexibility. For example, you would want to have different validation for portrait images than landscape ones, you could easily identify the image orientation and run your own custom code to do whatever.