Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Client-side image resolution/size validation

I'm designing a website for a printing company. They want an image size/resolution checker that will let their customers upload an image they want to print, and tell them if the image resolution is good enough for printing.

I'm using Adobe Muse, so I need a simple HTML and CSS solution to this without any server-side requirements.

This is what I have so far, based on this question:

window.URL = window.URL || window.webkitURL;
$("form").submit(function(e) {
    var form = this;
    e.preventDefault(); //Stop the submit for now

   //Replace with your selector to find the file input in your form var
   fileInput = $(this).find("input[type=file]")[0];
   file = fileInput.files && fileInput.files[0];
   if (file) {
       var img = new Image();
       img.src = window.URL.createObjectURL(file);

        img.onload = function() {
            var width = img.naturalWidth, height = img.naturalHeight;
            window.URL.revokeObjectURL( img.src );
            if( width == 400 && height == 300 ) {
                form.submit();
            } else { 
                //stop
            } 
        }; 
    } else {
        //No file was input or browser doesn't support client side reading
        form.submit();
    }
});

However, I don't get any popup message. What am I doing wrong?

like image 255
George Gibson Avatar asked Oct 02 '15 17:10

George Gibson


Video Answer


1 Answers

Your code contains a number of errors, which is why it isn't working. (I don't think the submit event is even being bound to the form, because your jQuery selector doesn't look right: it should be #form or .form)

Here's a working solution:

HTML

<form id="form" action="destination.html">
    <input type="file" id="filePicker" />
    <br/>
    <input type="submit" value="Submit" />
</form>

JS

var _URL = window.URL || window.webkitURL;

function isSupportedBrowser() {
    return window.File && window.FileReader && window.FileList && window.Image;
}

function getSelectedFile() {
    var fileInput = document.getElementById("filePicker");
    var fileIsSelected = fileInput && fileInput.files && fileInput.files[0];
    if (fileIsSelected)
        return fileInput.files[0];
    else
        return false;
}

function isGoodImage(file) {
    var deferred = jQuery.Deferred();
    var image = new Image();

    image.onload = function() {
        // Check if image is bad/invalid
        if (this.width + this.height === 0) {
            this.onerror();
            return;
        }

        // Check the image resolution
        if (this.width >= 400 && this.height >= 400) {
            deferred.resolve(true);
        } else {
            alert("The image resolution is too low.");
            deferred.resolve(false);
        }
    };

    image.onerror = function() {
        alert("Invalid image. Please select an image file.");
        deferred.resolve(false);
    }

    image.src = _URL.createObjectURL(file);

    return deferred.promise();
}


$("#form").submit(function(event) {
    var form = this;

    if (isSupportedBrowser()) {
        event.preventDefault(); //Stop the submit for now

        var file = getSelectedFile();
        if (!file) {
            alert("Please select an image file.");
            return;
        }

        isGoodImage(file).then(function(isGood) {
            if (isGood)
                form.submit();
        });
    }
});

isSupportedBrowser() makes sure that the user's browser supports the required functions before attempting to check the image.

getSelectedFile() makes sure the user has picked a file, and then passes the file data back.

isGoodImage() takes the file data and attempts to construct an image element from it. If onerror is fired, it's not an image or is a corrupted file. If onload is fired, it does a sanity check to make sure the image has valid dimensions, and then validates that the resolution is above 400x400.

Since onerror and onload events are fired asynchronously, the function needs to pass back a promise indicating the result of the validation.

Finally, the submit handler on the form ties all these method calls together and only allows the form to submit if the resolution check comes back good.

Link to fiddle: http://jsfiddle.net/uwj85m7d/7/

Edit As requested, a variant that shows divs containing error messages instead of alert popups: http://jsfiddle.net/uwj85m7d/8/


Further reading:

  • Is it possible to check dimensions of image before uploading? (good find!)
  • Get data from file input in JQuery
  • HTMLImageElement
  • image.onError event never fires, but image isn't valid data - need a work around
like image 173
Nate Barbettini Avatar answered Sep 30 '22 07:09

Nate Barbettini