1

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.

vsync
  • 118,978
  • 58
  • 307
  • 400
  • Did you see the image validation options? http://docs.fineuploader.com/branch/master/api/options.html#validation.image.maxHeight – Ray Nicholus Sep 03 '14 at 15:00
  • damn you're right I feel dumb. thanks and sorry for wasting your time. – vsync Sep 03 '14 at 15:01
  • No problem. We have a lot of docs, and it's easy to get lost in them. – Ray Nicholus Sep 03 '14 at 15:03
  • can I check that on the `submit` event? I don't see that data there, and i might only want to warn the user his imagine is low-res, rather than go through the validation path. is this still the case? - http://stackoverflow.com/a/23760457/104380 – vsync Sep 03 '14 at 15:10
  • Not at the moment. Fine Uploader internalizes this check and doesn't pass the data to event handlers. Since this is a potentially time-consuming bit of data to determine, we'd need another flag to control when this data is extracted and passed to event handlers. You can see how we determine image dimensions by looking at https://github.com/Widen/fine-uploader/blob/5.0.4/client/js/image-support/validation.image.js – Ray Nicholus Sep 03 '14 at 15:27
  • ...if you want, you can even construct an instance of `qq.ImageValidation` in your code, and call the `validate` method, which returns a promise. – Ray Nicholus Sep 03 '14 at 15:29
  • Found typo in source code - `@returns {qq.Promise} 'success' is called on the promise is the image is valid or`. Also, it cannot be instantiated without removing the call to the `log` function. but still, after I instantiate it, how would I use it to validate an image that had just been picked by the "browse" button (for example) – vsync Sep 03 '14 at 15:48
  • Not sure I understand the typo you are referring to. You can either pass `qq.log` as a second param to the constructor, or an empty function. You can perform this validation in an event handler, such as `validate` or `submit`. In either callback/event handler, you can get the associated `Blob` from Fine Uploader, which is required for `qq.ImageValidation` to validate the image based on the provided dimensions. Have a look at the unit tests at https://github.com/Widen/fine-uploader/blob/5.0.4/test/unit/validation.image.js – Ray Nicholus Sep 03 '14 at 15:55
  • well you have this call to `downloadFileAsBlob` in that unit test, and I don't know where that function is, so basically I don't know how to get the blob or each photo from the submit event.. – vsync Sep 03 '14 at 16:17
  • 1
    See the `getFile` API method. http://docs.fineuploader.com/branch/master/api/methods.html#getFile – Ray Nicholus Sep 03 '14 at 17:10
  • @RayNicholus - using `image.minWidth` gives me an ugly alert message, but what I need is to give a class to my uploader element once this happens. **but** the `validation` method doesn't state the reason of failure (I would expect the reason to be somewhere in the arguments). – vsync Sep 28 '14 at 11:13
  • @RayNicholus - the `getFile` method gives back nothing relevant to the file's dimensions (not even a blob). it only shows `lastModifiedDate, mozFullPath, name, path, size, type` (called in `submit` event) – vsync Oct 01 '14 at 12:11
  • it will always return a file or Blob. In fact, what you are describing are properties of a native Blob or file object. I suggest you look a bit closer. – Ray Nicholus Oct 01 '14 at 12:51
  • ok I FINALLY managed to this this using this **helpful** person's method - http://stackoverflow.com/a/7460303/104380 – vsync Oct 01 '14 at 13:04
  • Wow, that's a very inefficient way to solve this problem. How about looking at fine Uploader source for the correct approach? – Ray Nicholus Oct 01 '14 at 13:18
  • Thanks. I changed it the way you are doing it in the tests, but anyway, this is *async*, which means I cannot use any way of validation in conjunction of `submit` event, so I could return false in case of validation error, so the file won't get uploaded..tricky. – vsync Oct 01 '14 at 13:45
  • Sure you can. The onSubmit event handler accepts a promissory return type. http://docs.fineuploader.com/branch/master/features/async-tasks-and-promises.html – Ray Nicholus Oct 01 '14 at 14:33

1 Answers1

1

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.

Ray Nicholus
  • 19,538
  • 14
  • 59
  • 82
vsync
  • 118,978
  • 58
  • 307
  • 400