Drupal 8 / 9 : add custom validation on file upload

Sometimes you need to add other validation on file upload other then Maximum image resolution / Minimum image resolution / Maximum upload size (Drupal out of box validations), for example to check if image is 16:9 format or image dimension should be exact for example :

How to validate image on upload if it's 16:9 format ?

To do so you need to add upload_validators to field widget using hook_form_alter like the following:

/**
 * Implements hook_form_alter().
 */
function MODULENAME_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  switch ($form_id) {
    case 'node_article_form':
    case 'node_article_edit_form':
      $form['field_image']['widget'][0]['#upload_validators']['_validate_article_image'] = [];
      break;
  }
}

and then implement _validate_article_image callback:

/**
 * Validate article image.
 *
 * @param \Drupal\file\FileInterface $file
 *   File object.
 *
 * @return array
 *   Errors array.
 */
function _validate_article_image(FileInterface $file) {
  $errors = [];
  $image = \Drupal::service('image.factory')->get($file->getFileUri());
  if ($image->isValid()) {
    // Add your condition validations here!
    $width = $image->getWidth();
    $height = $image->getHeight();
    if ($width / $height != 16 / 9) {
      $errors[] = t("The image should be 16:9 format!");
    }
  }
  return $errors;
}

 

and that's it !