๐Ÿ“ค

S3 File Upload

๐Ÿ‘จโ€๐Ÿณ Chefโฑ๏ธ 30 minutes

๐Ÿ“‹ Suggested prerequisites

  • โ€ขAWS S3
  • โ€ขNext.js API

What you'll build

A file upload system where users can drag and drop images or documents, see a progress bar, and get the URL of the uploaded file. You'll use AWS S3 pre-signed URLs so files go directly to cloud storage without passing through your server, making it faster and cheaper. When finished, you'll have a reusable upload component with type and size validation that you can integrate into any form.


Why pre-signed URLs

  • File goes directly to S3 (doesn't pass through your server)
  • Faster and cheaper
  • Your server only generates the URL

Step 1: Ask an AI for the implementation

I need file upload to S3 with:
- Pre-signed URLs
- API route that generates the URL
- Upload component with drag & drop
- Progress bar
- Type and size validation
- TypeScript

Give me the complete code.

API Route

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const s3 = new S3Client({ region: 'us-east-1' })

export async function POST(request: Request) {
  const { filename, contentType } = await request.json()

  const command = new PutObjectCommand({
    Bucket: process.env.S3_BUCKET,
    Key: `uploads/${Date.now()}-${filename}`,
    ContentType: contentType
  })

  const url = await getSignedUrl(s3, command, { expiresIn: 3600 })
  return Response.json({ url })
}

Client

async function uploadFile(file: File) {
  // 1. Get pre-signed URL
  const { url } = await fetch('/api/upload', {
    method: 'POST',
    body: JSON.stringify({ filename: file.name, contentType: file.type })
  }).then(r => r.json())

  // 2. Upload directly to S3
  await fetch(url, {
    method: 'PUT',
    body: file,
    headers: { 'Content-Type': file.type }
  })
}

Next step

โ†’ Payments with Stripe