Skip to content

joseffie/express-image-validator

Repository files navigation

Express Image Validator

express-image-validator is a TypeScript library for validating received images in Express applications.

Uses req.files provided by express-fileupload.

Installation

$ npm install express-image-validator

Usage

When you upload an image, you often have to perform some checks on the files to get the expected result. For example, this includes validating MIME types, sizes, or whether files must be uploaded.

The API provides 3 middleware for image validation. Let's talk about each of them.

Basic image validation with isImage

isImage allows you to perform basic verification of an uploaded files:

  1. Using MIME type verification, reject files that are not images.
  2. Specify a limit on the number of images.
  3. Specify that at least one file should be uploaded.

It accepts 2 parameters:

  1. field: string | string[] – name or array of names of fields for validation
  2. options?: IsImageOptions – optional partial ValidationOptions object consisting of:
    • required: boolean.
    • limit: number.
    • allowedMimeTypes: ImageMimeTypes.

Example:

const { Router } = require('express');
const { isImage } = require('express-image-validator');
const router = Router();

const schema = isImage('avatar', {
  required: true,
  limit: 1,
});

router.post('/upload', schema, (req, res) => {
  res.send('Nice picture!');
});

This code snippet validates that the user is sure to upload only one image in the avatar field.

If you need to check multiple fields at once, just list them in the array:

const schema = isImage(['avatar', 'banner'], {
  required: true,
  limit: 1,
});

router.post('/upload', schema, (req, res) => {
  res.send('Nice pictures!');
});

In this case, the specified validation options will be applied for req.files.avatar and req.files.banner.

Advanced image validation with validateImageSingle

If you only need to check one field, but you need more options, use validateImageSingle.

It accepts 2 parameters:

  1. field: string – name of field for validation.
  2. options?: ValidationOptions – optional ValidationOptions object.

Example:

const { Router } = require('express');
const { validateImageSingle } = require('express-image-validator');
const router = Router();

const schema = validateImageSingle('avatar', {
  required: true,
  limit: 1,
  maxSize: 10,
  aspectRatio: 1,
});

router.post('/upload', schema, (req, res) => {
  res.send('Nice picture!');
});

This code snippet validates that the user sent a single square image of no more than 10 megabytes in size.

Advanced validation of multiple image fields with validateImage

If you need to validate multiple fields with different options using a single middleware, use `validateImage'.

This function accepts a single parameter field: FieldSet, combining the field and options from the previous functions. FieldSet is either a string with a field name or FieldSchema, or an array of strings with a field name or FieldSchemas.

If the parameter contains a string, it is transformed into an instance of FieldSchema with the default options object.

Example:

const { Router } = require('express');
const { validateImage } = require('express-image-validator');
const router = Router();

const schema = validateImage([
  'avatar',
  {
    name: 'banner',
    options: {
      limit: 1,
      aspectRatio: 16 / 9,
    },
  },
]);

router.post('/upload', schema, (req, res) => {
  res.send('Nice picture!');
});

This array for the validator will be transformed into something like:

[
  {
    name: 'avatar',
    options: {
      limit: null,
      minSize: 0,
      maxSize: null,
      required: false,
      aspectRatio: null,
      allowedMimeTypes: ['...'],
    },
  },
  {
    name: 'banner',
    options: {
      limit: 1,
      minSize: 0,
      maxSize: null,
      required: true,
      aspectRatio: 1.77777777778,
      allowedMimeTypes: ['...'],
    },
  },
];

You can also specify one field for validation, for example:

const schema = validateImage({
  name: 'avatar',
  options: {
    required: true,
    limit: 1,
  },
});

Handling validation errors

Validators do not report validation errors to users automatically. Instead, it is suggested to manually handle errors using the imageValidationResult function.

const { isImage, imageValidationResult } = require('express-image-validator');

router.post('/upload', isImage('avatar', { required: true }), (req, res) => {
  const result = imageValidationResult(req);

  if (!result.isEmpty()) {
    return res.status(200).json({ errors: result.array() });
  }

  return res.status(400);
});

Now, if the avatar image is not received on the POST /upload, we will get:

{
  "errors": [
    {
      "field": "avatar",
      "msg": "Missing required field",
      "value": true,
      "filename": null
    }
  ]
}

API

imageValidationResult()

imageValidationResult(req: Request): ValidationState

Extracts the validation results from a request, wraps them in a ValidationState object, and returns it.

ValidationState

The result object is a wrapper around the validation state of a request. It provides a couple of methods that you can use to determine if the request is valid or not.

isEmpty()

isEmpty(): boolean

Returns whether the request contains validation errors, and therefore whether it's valid or not.

array()

array(options?: { onlyFirstError?: boolean }): ValidationError[]

Returns a list of all errors from all validated fields.

const result = imageValidationResult(req).array();
// => [{ msg: 'Invalid file', field: 'field1' }, { msg: 'Invalid file', field: 'field1' }]

When options.onlyFirstError is set to true, then only the first error of each field is returned:

const result = imageValidationResult(req).array({ onlyFirstError: true });
// => [{ msg: 'Invalid file', field: 'field1' }]

mapped()

mapped(): Record<string, ValidationError>

Returns an object from field path to error. If a field has multiple errors, only the first one is returned.

const result = imageValidationResult(req).mapped();
// => { field1: { msg: 'Invalid value', ... }, field2: { msg: 'Invalid value', ... } }

throw()

throw(): void

If the result object has errors, then this method throws an error decorated with the same methods as the ValidationState type. This is useful if you wish to forward the errors to the error handler middleware of your Express.js application, for example.

If the result object has no errors, then this method does nothing.

const { isImage, imageValidationResult } = require('express-image-validator');

router.post('/upload', isImage('avatar', { required: true }), (req, res) => {
  try {
    imageValidationResult(req).throw();
    res.send('Nice picture!');
  } catch (e) {
    res.status(400).send({ errors: e.mapped() });
  }
});

ValidationOptions

The object of the image validation parameters. It can be specified empty in middleware, but it is always filled in with default values or user values as a result of the internal work of validators.

  • limit: number | null – maximum number of files in one field. null means that the number of files is unlimited.

  • minSize: number – minimum file size, specified in megabytes (Inside it is translated into bytes).

  • maxSize: number | null – maximum file size, specified in megabytes (Inside it is translated into bytes). null means that the maximum file size is unlimited.

  • required: boolean – specify that at least one file should be uploaded.

  • aspectRatio: number | null – required aspect ratio of the image with a tolerance of 5%. null means that the aspect ratio is not important.

  • allowedMimeTypes: ImageMimeTypes – array of allowed MIME image types. null means that all MIME types are allowed.

By default:

{
  limit: null,
  minSize: 0,
  maxSize: null,
  required: false,
  aspectRatio: null,
  allowedMimeTypes: null,
}

FieldSchema

An object of validation options for one specified field. Contains 2 properties:

  • name: string – name of field for validation.
  • options: ValidationOptions – instance of the ValidationOptions object.

FieldSet

A composite type that describes a set of fields and validation parameters for them, allowing the following data types:

  • Field: string | FieldSchema – the name of field to validate or the FieldSchema object.
  • Field[] – an array containing both strings of field names and FieldSchema objects.

Validators receive this value as an array FieldSchema[], so you can safely use any of the valid data types in your configuration.

isImage()

isImage(field: string | string[], options?: { limit?: number | null, required?: boolean, allowedMimeTypes: ImageMimeTypes | null }): RequestHandler

isImage allows you to perform basic verification of an uploaded files:

  1. Using MIME type verification, reject files that are not images.
  2. Specify a limit on the number of images.
  3. Specify that at least one file should be uploaded.

validateImageSingle()

validateImageSingle(field: string, options?: ValidationOptions): RequestHandler

see Advanced image validation with validateImageSingle

validateImage()

validateImage(field: FieldSet): RequestHandler

see Advanced image validation of multiple image fields with validateImage

AspectRatios

Common aspect ratios for images.

const AspectRatios: Record<string, number> = {
  LANDSCAPE_16_9: 16 / 9,
  LANDSCAPE_16_10: 16 / 10,
  LANDSCAPE_4_3: 4 / 3,
  LANDSCAPE_3_2: 3 / 2,
  LANDSCAPE_5_3: 5 / 3,
  PORTRAIT_9_16: 9 / 16,
  PORTRAIT_10_16: 10 / 16,
  PORTRAIT_2_3: 2 / 3,
  PORTRAIT_3_5: 3 / 5,
  SQUARE_1_1: 1 / 1,
  CINEMA_21_9: 21 / 9,
};

ImageMimeType

A supported MIME type for image files.

type ImageMimeType =
  | 'image/jpeg'
  | 'image/png'
  | 'image/gif'
  | 'image/webp'
  | 'image/bmp'
  | 'image/tiff'
  | 'image/svg+xml'
  | 'image/avif';

ImageMimeTypes

Non-empty array of supported image MIME types.

type ImageMimeTypes = [ImageMimeType, ...ImageMimeType[]];

License

This work is licensed under the MIT License (see the LICENSE file).

About

Validator of various image parameters in Express.js applications

Topics

Resources

License

Stars

Watchers

Forks