Validation

Validate files before upload to provide immediate feedback and prevent unnecessary API calls.

Overview

Dropper provides comprehensive validation utilities:

  • File Type Validation: Check MIME types and extensions
  • File Size Validation: Enforce size limits
  • File Count Validation: Limit number of files
  • Batch Validation: Validate multiple files at once
  • Type Checkers: Helper functions for common file types

Validate Files

Validate multiple files against a set of rules:

import { validateFiles } from '@dropper/core'

const errors = validateFiles(files, {
  accept: 'image/*',
  maxSize: 5 * 1024 * 1024, // 5MB
  maxFiles: 10,
})

if (errors.length > 0) {
  errors.forEach((error) => {
    console.error(`${error.file.name}: ${error.message}`)
  })
} else {
  console.log('All files are valid!')
}

ValidationRules

interface ValidationRules {
  accept?: string     // Accepted file types (MIME types or extensions)
  maxSize?: number    // Maximum file size in bytes
  maxFiles?: number   // Maximum number of files
}

Accept Patterns

The accept parameter supports multiple formats:

MIME Types

// Exact MIME type
validateFiles(files, { accept: 'image/jpeg' })

// Wildcard MIME type
validateFiles(files, { accept: 'image/*' })
validateFiles(files, { accept: 'video/*' })
validateFiles(files, { accept: 'audio/*' })

// Multiple MIME types
validateFiles(files, { accept: 'image/jpeg,image/png,image/gif' })

File Extensions

// Single extension
validateFiles(files, { accept: '.pdf' })

// Multiple extensions
validateFiles(files, { accept: '.jpg,.jpeg,.png,.gif' })

// Mixed MIME types and extensions
validateFiles(files, { accept: 'image/*,.pdf' })

ValidationError

Each validation error contains:

interface ValidationError {
  file: File           // The file that failed validation
  type: 'type' | 'size' | 'count'  // Error type
  message: string      // Human-readable error message
}

Individual Validators

Validate File Type

Check if a file matches the accepted types:

import { validateFileType } from '@dropper/core'

const isValid = validateFileType(file, 'image/*')

if (!isValid) {
  console.error('File type not allowed')
}

Validate File Size

Check if a file is within the size limit:

import { validateFileSize } from '@dropper/core'

const maxSize = 10 * 1024 * 1024 // 10MB
const isValid = validateFileSize(file, maxSize)

if (!isValid) {
  console.error('File too large')
}

Validate File Count

Check if the number of files is within the limit:

import { validateFileCount } from '@dropper/core'

const isValid = validateFileCount(files, 5)

if (!isValid) {
  console.error('Too many files')
}

Type Checkers

Helper functions to check common file types:

isImage()

Check if a file is an image:

import { isImage } from '@dropper/core'

if (isImage(file)) {
  console.log('This is an image file')
}

isVideo()

Check if a file is a video:

import { isVideo } from '@dropper/core'

if (isVideo(file)) {
  console.log('This is a video file')
}

isPDF()

Check if a file is a PDF:

import { isPDF } from '@dropper/core'

if (isPDF(file)) {
  console.log('This is a PDF file')
}

Validate Publishable Key

Validate the format of a publishable key:

import { validatePublishableKey } from '@dropper/core'

const key = 'pk_dropper_test_abc123'
const isValid = validatePublishableKey(key)

if (!isValid) {
  console.error('Invalid publishable key format')
}

Valid key format: pk_dropper_{environment}_{key}

  • Environment: test or live
  • Key: Alphanumeric string

Complete Examples

Image Upload Validation

import { validateFiles, isImage } from '@dropper/core'

function validateImageUpload(files: File[]) {
  // Validate with rules
  const errors = validateFiles(files, {
    accept: 'image/jpeg,image/png,image/gif,image/webp',
    maxSize: 5 * 1024 * 1024, // 5MB
    maxFiles: 10,
  })
  
  if (errors.length > 0) {
    errors.forEach((error) => {
      console.error(`${error.file.name}: ${error.message}`)
    })
    return false
  }
  
  // Additional check: Ensure all are images
  const allImages = files.every((file) => isImage(file))
  if (!allImages) {
    console.error('All files must be images')
    return false
  }
  
  return true
}

Document Upload Validation

import { validateFiles, isPDF } from '@dropper/core'

function validateDocumentUpload(files: File[]) {
  const errors = validateFiles(files, {
    accept: '.pdf,.doc,.docx,.txt',
    maxSize: 10 * 1024 * 1024, // 10MB
    maxFiles: 5,
  })
  
  if (errors.length > 0) {
    showErrors(errors)
    return false
  }
  
  return true
}

Video Upload Validation

import { validateFiles, isVideo } from '@dropper/core'

function validateVideoUpload(files: File[]) {
  const errors = validateFiles(files, {
    accept: 'video/*',
    maxSize: 100 * 1024 * 1024, // 100MB
    maxFiles: 3,
  })
  
  if (errors.length > 0) {
    errors.forEach((error) => {
      if (error.type === 'size') {
        console.error(`${error.file.name} is too large (max 100MB)`)
      } else if (error.type === 'type') {
        console.error(`${error.file.name} is not a video file`)
      } else if (error.type === 'count') {
        console.error('Maximum 3 videos allowed')
      }
    })
    return false
  }
  
  return true
}

Form Validation

import { validateFiles } from '@dropper/core'

function handleFileInput(e: React.ChangeEvent<HTMLInputElement>) {
  const files = Array.from(e.target.files || [])
  
  const errors = validateFiles(files, {
    accept: 'image/*,video/*',
    maxSize: 50 * 1024 * 1024, // 50MB
    maxFiles: 20,
  })
  
  if (errors.length > 0) {
    // Show errors to user
    const errorMessages = errors.map((err) => err.message).join('\n')
    alert(errorMessages)
    
    // Clear input
    e.target.value = ''
    return
  }
  
  // Proceed with upload
  uploadFiles(files)
}

Custom Error Messages

import { validateFiles, formatFileSize } from '@dropper/core'

function validateWithCustomMessages(files: File[], rules: ValidationRules) {
  const errors = validateFiles(files, rules)
  
  return errors.map((error) => {
    switch (error.type) {
      case 'type':
        return `"${error.file.name}" is not an allowed file type`
      case 'size':
        return `"${error.file.name}" exceeds the maximum size of ${formatFileSize(rules.maxSize || 0)}`
      case 'count':
        return `You can only upload ${rules.maxFiles} files at a time`
      default:
        return error.message
    }
  })
}

React Integration

File Input with Validation

import { useState } from 'react'
import { validateFiles } from '@dropper/core'

function FileUploadForm() {
  const [errors, setErrors] = useState<string[]>([])
  
  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || [])
    
    const validationErrors = validateFiles(files, {
      accept: 'image/*',
      maxSize: 5 * 1024 * 1024,
      maxFiles: 10,
    })
    
    if (validationErrors.length > 0) {
      setErrors(validationErrors.map((err) => err.message))
      e.target.value = '' // Clear input
      return
    }
    
    setErrors([])
    // Proceed with upload
    uploadFiles(files)
  }
  
  return (
    <div>
      <input
        type="file"
        multiple
        accept="image/*"
        onChange={handleFileChange}
      />
      
      {errors.length > 0 && (
        <div className="errors">
          {errors.map((error, i) => (
            <div key={i} className="error">{error}</div>
          ))}
        </div>
      )}
    </div>
  )
}

Best Practices

1. Validate Before Upload

Always validate files before uploading:

const errors = validateFiles(files, rules)

if (errors.length > 0) {
  showErrors(errors)
  return
}

// Only upload if validation passes
await uploadFiles(files)

2. Provide Clear Feedback

Show specific error messages:

errors.forEach((error) => {
  showError(`${error.file.name}: ${error.message}`)
})

3. Match HTML Accept Attribute

Keep validation rules in sync with HTML:

// HTML
<input type="file" accept="image/*" />

// Validation
validateFiles(files, { accept: 'image/*' })

4. Use Appropriate Size Limits

Set realistic size limits based on file type:

// Images: 5-10MB
validateFiles(files, { accept: 'image/*', maxSize: 5 * 1024 * 1024 })

// Videos: 50-100MB
validateFiles(files, { accept: 'video/*', maxSize: 100 * 1024 * 1024 })

// Documents: 10-20MB
validateFiles(files, { accept: '.pdf,.doc', maxSize: 10 * 1024 * 1024 })

5. Validate Early and Often

Validate at multiple points:

// On file selection
handleFileSelect(files) {
  const errors = validateFiles(files, rules)
  if (errors.length > 0) return
  
  // Store files
  setSelectedFiles(files)
}

// Before upload
handleUpload() {
  // Re-validate before upload
  const errors = validateFiles(selectedFiles, rules)
  if (errors.length > 0) return
  
  // Upload
  await uploadFiles(selectedFiles)
}

Common Validation Rules

Images

{
  accept: 'image/jpeg,image/png,image/gif,image/webp',
  maxSize: 5 * 1024 * 1024,  // 5MB
  maxFiles: 10
}

Videos

{
  accept: 'video/mp4,video/webm,video/ogg',
  maxSize: 100 * 1024 * 1024,  // 100MB
  maxFiles: 3
}

Documents

{
  accept: '.pdf,.doc,.docx,.txt,.xlsx,.pptx',
  maxSize: 10 * 1024 * 1024,  // 10MB
  maxFiles: 20
}

Audio

{
  accept: 'audio/mpeg,audio/wav,audio/ogg',
  maxSize: 20 * 1024 * 1024,  // 20MB
  maxFiles: 50
}

Next Steps