Adonis Open Swagger

File Helpers

Handle file uploads in your API documentation with file helper functions

File helpers provide a convenient way to define file upload schemas in your OpenAPI documentation. They work seamlessly with any schema library (VineJS, TypeBox, Zod) and integrate with the @SwaggerRequestBody decorator.

Available File Helpers

Adonis Open Swagger provides four file helper functions that generate OpenAPI-compatible file schemas:

FunctionDescription
openapiFile(options?)Generic file schema (works with any validator)
vineFile(options?)VineJS-compatible file schema (use inside vine.object())
typeboxFile(options?)TypeBox-compatible file schema (use inside Type.Object())
zodFile(options?)Zod-compatible file schema (use inside z.object())

All functions accept the same options and produce identical output. The aliases exist for semantic consistency with your chosen schema library.

FileOptions

interface FileOptions {
  description?: string; // Description of the file field
  multiple?: boolean; // Accept multiple files (default: false)
  minItems?: number; // Min files (only when multiple: true)
  maxItems?: number; // Max files (only when multiple: true)
}

Basic Usage

Single File Upload

import { openapiFile } from "adonis-open-swagger";

openapiFile({ description: "Profile picture" });
// Generates: { type: "string", format: "binary", description: "Profile picture" }

Multiple Files Upload

import { openapiFile } from "adonis-open-swagger";

openapiFile({
  description: "Gallery images",
  multiple: true,
  minItems: 1,
  maxItems: 10,
});
// Generates: {
//   type: "array",
//   items: { type: "string", format: "binary" },
//   description: "Gallery images",
//   minItems: 1,
//   maxItems: 10
// }

Integration with Schema Libraries

VineJS

import { SwaggerRequestBody, SwaggerInfo, vineFile } from "adonis-open-swagger";
import vine from "@vinejs/vine";

export default class CampaignsController {
  @SwaggerInfo({
    tags: ["Campaigns"],
    summary: "Create campaign with file upload",
    description: "Upload a CSV file with customer data",
  })
  @SwaggerRequestBody(
    "Campaign data with file",
    vine.object({
      name: vine.string(),
      file: vineFile({ description: "CSV file with customers" }),
    }),
    { contentType: "multipart/form-data" }
  )
  async store({ request }: HttpContext) {
    // Handle file upload
  }
}

TypeBox

import {
  SwaggerRequestBody,
  SwaggerInfo,
  typeboxFile,
} from "adonis-open-swagger";
import { Type } from "@sinclair/typebox";

export default class UploadsController {
  @SwaggerInfo({
    tags: ["Uploads"],
    summary: "Upload document",
  })
  @SwaggerRequestBody(
    "Document upload",
    Type.Object({
      title: Type.String(),
      document: typeboxFile({ description: "PDF document" }),
    }),
    { contentType: "multipart/form-data" }
  )
  async upload({ request }: HttpContext) {
    // Handle file upload
  }
}

Zod

import { SwaggerRequestBody, SwaggerInfo, zodFile } from "adonis-open-swagger";
import { z } from "zod";

export default class MediaController {
  @SwaggerInfo({
    tags: ["Media"],
    summary: "Upload media files",
  })
  @SwaggerRequestBody(
    "Media upload",
    z.object({
      caption: z.string(),
      images: zodFile({
        description: "Image files",
        multiple: true,
        maxItems: 5,
      }),
    }),
    { contentType: "multipart/form-data" }
  )
  async upload({ request }: HttpContext) {
    // Handle file upload
  }
}

Content Types

When using file helpers, you must set the appropriate content type in @SwaggerRequestBody:

Content TypeUse Case
multipart/form-dataFile uploads and mixed data
@SwaggerRequestBody(
  "File upload with metadata",
  vine.object({
    name: vine.string(),
    file: vineFile({ description: "Upload file" }),
  }),
  { contentType: "multipart/form-data" } // Required for file uploads
)

Complete Example

Here's a complete example of a file upload endpoint with full documentation:

import {
  SwaggerInfo,
  SwaggerRequestBody,
  SwaggerResponse,
  vineFile,
} from "adonis-open-swagger";
import vine from "@vinejs/vine";
import type { HttpContext } from "@adonisjs/core/http";

export default class DocumentsController {
  @SwaggerInfo({
    tags: ["Documents"],
    summary: "Upload documents",
    description: "Upload one or more documents with metadata",
  })
  @SwaggerRequestBody(
    "Document upload payload",
    vine.object({
      title: vine.string().minLength(1).maxLength(255),
      description: vine.string().optional(),
      files: vineFile({
        description: "Document files (PDF, DOCX)",
        multiple: true,
        minItems: 1,
        maxItems: 10,
      }),
    }),
    { contentType: "multipart/form-data" }
  )
  @SwaggerResponse(201, "Documents uploaded successfully")
  @SwaggerResponse(400, "Invalid file format")
  @SwaggerResponse(413, "File size too large")
  async store({ request, response }: HttpContext) {
    const files = request.files("files");
    // Process uploaded files
    return response.created({ message: "Documents uploaded" });
  }
}

Last updated on