0

I'm trying to valdiate a multiple image upload using jQuery. The validation proccess get the images dimensions and check if it is greater than 338x450. But I know very little about javascript. Can someone help me? Here's the code I'm trying:

HTML:

<input class="form-control" id="ads-photos" name="ads-photos[]" type="file" accept="image/jpeg, image/jpg" multiple />

javascript

var isFilesOk;

$('#ads-photos').change(function (evt) {
    validateDimensions();

}); 

function validateDimensions() {
    var fi = document.getElementById('ads-photos');
    if (fi.files.length > 0) {      
      for (var i = 0; i <= fi.files.length - 1; i++) {
          var fileName, fileExtension, fileSize, fileType, dateModified;
          fileName = fi.files.item(i).name;
          fileExtension = fileName.replace(/^.*\./, '');
          if (fileExtension == 'jpg' || fileExtension == 'jpeg') {
             if (readImageFile(fi.files.item(i))) {
                 alert(isFilesOk);
             } else {
                alert(isFilesOk);
             }            
            }
        }
    }
    // GET THE IMAGE WIDTH AND HEIGHT USING fileReader() API.
    function readImageFile(file) {
        var reader = new FileReader(); // CREATE AN NEW INSTANCE.
        reader.onload = function (e) {
            var img = new Image();      
            img.src = e.target.result;

            img.onload = function () {
                var w = this.width;
                var h = this.height;
                if (this.width >= 338 && this.height >= 450) {
                    isFilesOk = true;
                } else {
                     isFilesOk = false;
                }
            }
        };
        reader.readAsDataURL(file);
        return isFilesOk;
    }
}

A example link

The above code needs analyze all the images sended by the user to know if they all have minimum required dimensions. But I'm not getting it to work.

2
  • What is not happening with the code that you are expecting to happen or what is the error? Commented Aug 11, 2020 at 22:14
  • Hello @imvain2! When loading images, the first alert displays "undefined". I need that the script to analyze all the images sended by the user to know if they all have minimum required dimensions. Commented Aug 11, 2020 at 22:34

1 Answer 1

1

The issue here is that the readImageFile method is asynchronous. The work it's doing happens later, after it's executed when the onload event is triggered on the file.

The best solution will depend a little on the environment you're targeting (eg: whether you need to support old IE, etc), but if you're able to use modern JS with Promises, this will be easier.

Basically, for each file that's selected, you want to get a Promise indicating whether the file is okay or not. A good way to do this is map the array to an array of Promises and use Promise.all to get a callback when they're all done.

Here's the method to get that for a single file:

function fileIsValid(file) {
  return new Promise((resolve) => {
    var reader = new FileReader(); // CREATE AN NEW INSTANCE.
    reader.onload = function (e) {
      var img = new Image();      
      img.src = e.target.result;

      img.onload = function () {
        var w = this.width;
        var h = this.height;
        const isValid = w >= 338 && h >= 450;
        resolve(isValid);
      };
    };
    reader.readAsDataURL(file);
  });
}

And then using this method:

const fi = document.getElementById('ads-photos');
const promises = [];
for (let i = 0; i <= fi.files.length - 1; i++) {
  const file = fi.files.item(i);
  if (/\.jpe?g$/.test(file.name)) {
    promises.push(fileIsValid(file));
  }
}
Promise.all(promises).then((results) => {
  // results is an array of booleans
  const allValid = results.every(Boolean);
  if (allValid) {
    alert('Yeah!');
  } else {
    alert('Nope');
  }
});

There's a few things to note here:

  • you could make it shortcut once a single error is found by making the promise reject if it's invalid, and Promise.all then won't wait for any other pending promises. This is a bit of a style question about whether failed validation should result in a rejected promise. Up to you on that. In this case, it's reading from a local file system and I presume they'll be selecting a relatively small number of files, so short-circuiting probably won't make any noticeable difference.
  • it doesn't handle actual errors (eg: what if a file is unable to be loaded?).
Sign up to request clarification or add additional context in comments.

1 Comment

Thank'u @nickf. Works great!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.