File Upload Demo

This demo shows a styled native file input with:

  • Drag-and-drop support
  • File type and size validation (JPG, JPEG, PNG, max 1MB)
  • Simulated presigned URL request before upload
  • Fake progress indicator that completes on "upload"
  • Single file only (no multi-file)
  • Error simulation controls

The core logic is written in vanilla TypeScript, with the UI connected via Vue. No actual files are uploaded anywhere.

Please upload an image.

Choose a file or drag and drop it here

Files can be JPG, JPEG or PNG & 1MB max

Recommended file size: 1000x1000 pixels

Error Simulation

Toggle these options before selecting a file to simulate error scenarios.

Below is a visual reference of all UI states and error scenarios covered by this component.

How it Works

  1. File Selection: Select a file via the button or drag-and-drop
  2. Validation: File type and size are validated client-side
  3. Presigned URL: A simulated delay represents fetching a presigned URL from the server
  4. Upload Progress: A fake progress bar animates to completion
  5. Complete: The Save button becomes enabled

Retry Logic

Server errors (presigned URL failures and upload failures) show a Retry button that allows the user to attempt the upload again without re-selecting the file. Validation errors (wrong file type, file too large) do not show a retry button since those require selecting a different file.

Architecture

The upload logic is split into pure TypeScript functions:

  • validateFile() - Validates file type and size
  • formatFileSize() - Converts bytes to human-readable format
  • requestPresignedUrl() - Simulates server request for upload URL (supports failure simulation)
  • simulateUpload() - Runs fake progress animation (supports failure at configurable percentage)
  • uploadFile() - Orchestrates the full flow with simulation options

This separation keeps the Vue component thin and makes the logic testable and reusable.