65

I have an upload control for uploading the images to the server, but before uploading I just want to make sure if the images are of correct dimensions. Is there anything on client side that can be done with JavaScript?

Penny Liu
  • 7,720
  • 5
  • 40
  • 66
Sabby62
  • 1,657
  • 2
  • 24
  • 35
  • 4
    In the HTML5 File API this is possible, otherwise it's not! – adeneo Nov 26 '12 at 19:59
  • This should answer your question: http://stackoverflow.com/questions/5173796/html5-get-image-dimension – Joshua Burns Nov 26 '12 at 20:03
  • Yes, it is possible. http://stackoverflow.com/questions/961913/image-resize-before-upload – Jaroslav Trsek Nov 26 '12 at 20:04
  • 1
    Of course (as with *all* validation), though it may be sensible to check on the client side, any client can fake it and you should still validate on the server side too. –  Nov 26 '12 at 20:08

7 Answers7

73

You could check them before submitting form:

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 {
                //fail
            }
        };
    }
    else { //No file was input or browser doesn't support client side reading
        form.submit();
    }

});

This only works on modern browsers so you still have to check the dimensions on server side. You also can't trust the client so that's another reason you must check them server side anyway.

Esailija
  • 130,716
  • 22
  • 250
  • 308
  • No kidding, 'createObjectURL' doesn't work on IE just until recently... What a shame. http://caniuse.com/#search=createObjectURL – HelpNeeder Apr 12 '16 at 10:07
47

Yes, HTML5 API supports this.

http://www.w3.org/TR/FileAPI/

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

$("#file").change(function(e) {

    var image, file;

    if ((file = this.files[0])) {

        image = new Image();

        image.onload = function() {

            alert("The image width is " +this.width + " and image height is " + this.height);
        };

        image.src = _URL.createObjectURL(file);


    }

});​

DEMO (tested on chrome)

Gurpreet Singh
  • 19,141
  • 5
  • 40
  • 56
  • 2
    @AlienWebguy - of course it is, see this [**SITE**](http://base64img.com), when dropping or selecting an image the name, filesize and dimensions are updated right away without ever uploading the image to the server. – adeneo Nov 26 '12 at 20:07
2

Might be a bit late but here's a modern ES6 version of the accepted answer using promises

const getUploadedFileDimensions: file => new Promise((resolve, reject) => {
    try {
        let img = new Image()

        img.onload = () => {
            const width  = img.naturalWidth,
                  height = img.naturalHeight

            window.URL.revokeObjectURL(img.src)

            return resolve({width, height})
        }

        img.src = window.URL.createObjectURL(file)
    } catch (exception) {
        return reject(exception)
    }
})

You'd call it like this

getUploadedFileDimensions(file).then(({width, height}) => {
    console.log(width, height)
})
Klemen Tusar
  • 7,916
  • 4
  • 26
  • 26
1

To make things simple, use a javascript image processing framework like fabric.js, processing.js and MarvinJ.

In the case of MarvinJ, simply loads the image in the client side and use the methods getWidth() and getHeight() to check the image's dimensions. Having the dimensions you can allow the file submission or notify the user about the incompatible dimension.

Example:

var image = new MarvinImage();
image.load("https://i.imgur.com/oOZmCas.jpg", imageLoaded);

function imageLoaded(){
  document.getElementById("result").innerHTML += image.getWidth()+","+image.getHeight();
}
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
<div id="result"></div>
1

If you don't need to handle svg files and can limit yourself to newest browsers, then you can use the createImageBitmap function to make a Promise based one liner:

if(typeof createImageBitmap !== "function") {
  console.error("Your browser doesn't support this method");
  // fallback to URL.createObjectURL + <img>
}

inp.oninput = e => {
  createImageBitmap(inp.files[0])
    .then((bmp) => console.log(bmp.width, bmp.height))
    .catch(console.error);
}
<input type="file" id="inp" accept="image/*">
Kaiido
  • 87,051
  • 7
  • 143
  • 194
0

An extension of @Klemen Tusar's anser for multiple files:

const loadImage = file => new Promise((resolve, reject) => {
    try {
        const image = new Image();

        image.onload = function () {
            resolve(this)
        };

        image.onerror = function () {
            reject("Invalid image. Please select an image file.");
        }

        image.src = window.URL.createObjectURL(file);
    } catch (e) {
        reject(e)
    }
})

const loadImagesArray = async files => {
    let images = Array(files.length)
    await Promise.all(files.map((file, i) => (async () => {
        const loadedImage = await loadImage(file)
        images[i] = loadedImage
    })()))
    return images
}

Then you can check stuff on loaded images simply as follows:

const loadedImages = await loadImagesArray(e.currentTarget.files)
for(const loadedImage of loadedImages) {
    console.log(loadedImage.width, loadedImage.height)
}
Adam
  • 951
  • 1
  • 12
  • 13
-3

Give this a shot. I've used this in the past. https://github.com/valums/file-uploader

webNoob
  • 186
  • 1
  • 9
  • 4
    The OP says they already have an upload control but wants an extra feature. Thowing them a completely new upload control isn't really a great answer. All they want is dimensions. Anyway, that uploader has now been moved to here: https://github.com/FineUploader/fine-uploader – TheCarver Feb 21 '15 at 01:38