UNPKG

express-image-validator

Version:

Validator of various image parameters in Express.js applications

423 lines (308 loc) 11.8 kB
# Express Image Validator `express-image-validator` is a TypeScript library for validating received images in Express applications. Uses `req.files` provided by [express-fileupload](https://www.npmjs.com/package/express-fileupload). - [Installation](#installation) - [Usage](#usage) - [Basic image validation with `isImage`](#basic-image-validation-with-isimage) - [Advanced image validation with `validateImageSingle`](#advanced-image-validation-with-validateimagesingle) - [Advanced validation of multiple image fields with `validateImage`](#advanced-validation-of-multiple-image-fields-with-validateimage) - [Handling validation errors](#handling-validation-errors) - [API](#api) - [`imageValidationResult()`](#imagevalidationresult) - [`ValidationState`](#validationstate) - [`ValidationOptions`](#validationoptions) - [`FieldSchema`](#fieldschema) - [`FieldSet`](#fieldset) - [`isImage()`](#isimage) - [`validateImageSingle()`](#validateimagesingle) - [`validateImage()`](#validateimage) - [`AspectRatios`](#aspectratios) - [`ImageMimeType`](#imagemimetype) - [`ImageMimeTypes`](#imagemimetypes) - [License](#license) ## 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](#validationoptions) object consisting of: - `required: boolean`. - `limit: number`. - `allowedMimeTypes: ImageMimeTypes`. Example: ```js 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: ```js 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](#validationoptions) object. Example: ```js 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](#fieldset) is either a string with a field name or [FieldSchema](#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](#validationoptions) object. Example: ```js 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: ```js [ { 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: ```js 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. ```js 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: ```json { "errors": [ { "field": "avatar", "msg": "Missing required field", "value": true, "filename": null } ] } ``` ## API ### `imageValidationResult()` ```js imageValidationResult(req: Request): ValidationError[] ``` Extracts the validation results from a request, wraps them in a [ValidationState](#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()` ```ts isEmpty(): boolean ``` Returns whether the request contains validation errors, and therefore whether it's valid or not. #### `array()` ```ts array(options?: { onlyFirstError?: boolean }): ValidationError[] ``` Returns a list of all errors from all validated fields. ```ts 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: ```ts const result = imageValidationResult(req).array({ onlyFirstError: true }); // => [{ msg: 'Invalid file', field: 'field1' }] ``` #### `mapped()` ```ts mapped(): Record<string, ValidationError> ``` Returns an object from field path to error. If a field has multiple errors, only the first one is returned. ```ts const result = imageValidationResult(req).mapped(); // => { field1: { msg: 'Invalid value', ... }, field2: { msg: 'Invalid value', ... } } ``` #### `throw()` ```ts 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. ```js 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: ```ts { 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](#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](#fieldschema) object. - `Field[]` – an array containing both strings of field names and [FieldSchema](#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()` ```ts 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()` ```ts validateImageSingle(field: string, options?: ValidationOptions): RequestHandler ``` see [Advanced image validation with `validateImageSingle`](#advanced-image-validation-with-validateimagesingle) ### `validateImage()` ```ts validateImage(field: FieldSet): RequestHandler ``` see [Advanced image validation of multiple image fields with `validateImage`](#advanced-validation-of-multiple-image-fields-with-validateimage) ### `AspectRatios` Common aspect ratios for images. ```ts 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. ```ts 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. ```ts type ImageMimeTypes = [ImageMimeType, ...ImageMimeType[]]; ``` # License This work is licensed under the MIT License (see the [LICENSE](https://github.com/joseffie/express-image-validator/blob/main/LICENSE) file).