Next.js

File Upload

Handling file uploads in Next.js using the App Router and API routes.

Client-Side Upload Form: A React component using FormData to send files to the server.
📄components/UploadForm.tsx
TSX
'use client';
import { useState } from 'react';

export default function UploadForm() {
  const [file, setFile] = useState<File>();

  const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!file) return;

    try {
      const data = new FormData();
      data.set('file', file);

      const res = await fetch('/api/upload', {
        method: 'POST',
        body: data
      });
      
      if (!res.ok) throw new Error(await res.text());
    } catch (e: any) {
      console.error(e);
    }
  };

  return (
    <form onSubmit={onSubmit}>
      <input
        type="file"
        name="file"
        onChange={(e) => setFile(e.target.files?.[0])}
      />
      <button type="submit">Upload</button>
    </form>
  );
}
API Route for Upload: An App Router API handler that processes the uploaded file and saves it locally.
📄app/api/upload/route.ts
TS
import { NextRequest, NextResponse } from 'next/server';
import { writeFile } from 'fs/promises';
import { join } from 'path';

export async function POST(request: NextRequest) {
  const data = await request.formData();
  const file: File | null = data.get('file') as unknown as File;

  if (!file) {
    return NextResponse.json({ success: false });
  }

  const bytes = await file.arrayBuffer();
  const buffer = Buffer.from(bytes);

  const path = join(process.cwd(), 'public/uploads', file.name);
  await writeFile(path, buffer);
  
  console.log(`Open ${path} to see the uploaded file`);

  return NextResponse.json({ success: true });
}