ViteHub

Validate uploads

Validate uploaded Blob bodies by size and type before writing them to storage.

Validate user uploads before they cross the storage boundary. The route should pass a known-safe Blob to blob.put().

Validate a File Upload

import { createError, defineEventHandler, readFormData } from 'h3'
import { blob, ensureBlob } from '@vitehub/blob'

export default defineEventHandler(async (event) => {
  const form = await readFormData(event)
  const file = form.get('file')

  if (!(file instanceof Blob)) {
    throw createError({ statusCode: 400, statusMessage: 'Expected a file upload.' })
  }

  ensureBlob(file, {
    maxSize: '1MB',
    types: ['image'],
  })

  return await blob.put('upload.png', file, {
    addRandomSuffix: true,
    prefix: 'uploads',
  })
})

Validate Exact MIME Types

Use broad groups for simple rules and exact MIME types for strict rules.

ensureBlob(file, {
  maxSize: '8MB',
  types: ['image/png', 'image/jpeg'],
})

PDF files can use either the broad pdf type or the exact MIME type:

ensureBlob(file, {
  maxSize: '4MB',
  types: ['pdf'],
})

Size Values

maxSize accepts power-of-two size values with these units:

UnitExample
B256B
KB8KB
MB1MB
GB1GB

Customize the Route Error

ensureBlob() throws an H3 400 error. Catch it only when the route needs a different message.

try {
  ensureBlob(file, { maxSize: '1MB', types: ['image'] })
}
catch {
  throw createError({
    statusCode: 400,
    statusMessage: 'Upload an image smaller than 1MB.',
  })
}

Avoid These Mistakes

MistakeFix
Calling ensureBlob(file) with no rulesPass maxSize, types, or both.
Checking only the filename extensionValidate the uploaded Blob.type.
Writing the file before validationCall ensureBlob() before blob.put().
Copyright © 2026