Skip to content
AzuAzu

Uploads

Products need photos, and orders need invoices. file and image fields upload to a Drive disk and store the file’s key on the model.

The demo’s product thumbnail:

app/admin/resources/product_resource.ts (fields)
fields: [
field.text('name').section('Details'),
// inertia/admin/components/sku_input.tsx
field.text('sku').component('SkuInput').section('Details'),
field.decimal('price').section('Pricing').min(0),
field.belongsTo('category').section('Organisation').searchable('name'),
field.manyToMany('tags').section('Organisation').searchable('name'),
field
.select('status')
.section('Organisation')
.options({ draft: 'Draft', published: 'Published' }),
field.richText('description').section('Media'),
field.image('thumbnail').section('Media').maxSize('2mb'),
],

Uploads need Drive. A resource with file or image fields fails at boot without it.

Terminal window
node ace add @adonisjs/drive
  • The disk: the field’s .disk('s3'), else defaultDisk in config/azu.ts, else Drive’s default disk.
  • The key: <resource>/<field>/<uuid>.<ext>. Your validator sees that key, so validate it as a string.

The demo’s product validator:

app/validators/product.ts (part)
/** A Drive key: Azu checks and stores the upload, then validates its key */
thumbnail: vine.string().maxLength(255).nullable().optional(),

The server checks the size and detects the file type. It checks file signatures where available. For text, CSV, SVG, and HTML, it uses the extension. ZIP-based Office files share a signature, so the extension distinguishes them.

  • Size: .maxSize('2mb'). The default is 5mb for images and 10mb for files.
  • Type: .accept('application/pdf') replaces the default list. Images default to JPEG, PNG, WebP, GIF, and AVIF. Files add PDF, text, CSV, Office documents, and ZIP.
  • An upload is checked first. If the save then fails validation, nothing is stored.
  • Leaving a file field out of the request keeps the stored file. Sending it empty removes it.
  • A replaced or removed file is deleted from the disk after the save commits.
  • Deleting a record deletes its stored files after the delete commits.