DEV Community

Alex Spinov
Alex Spinov

Posted on

UploadThing Has a Free API That Makes File Uploads in React Dead Simple

UploadThing is the file upload library built for TypeScript. It handles presigned URLs, validation, and storage — so you just define what files you accept.

Define Upload Routes

import { createUploadthing, type FileRouter } from "uploadthing/next";

const f = createUploadthing();

export const uploadRouter = {
  imageUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 4 } })
    .middleware(async ({ req }) => {
      const user = await auth(req);
      if (!user) throw new Error("Unauthorized");
      return { userId: user.id };
    })
    .onUploadComplete(async ({ metadata, file }) => {
      console.log("Upload complete:", file.url);
      await db.insert({ userId: metadata.userId, fileUrl: file.url });
    }),

  csvUploader: f({ "text/csv": { maxFileSize: "16MB" } })
    .middleware(async () => ({ uploadedAt: new Date() }))
    .onUploadComplete(({ file }) => {
      console.log("CSV uploaded:", file.name, file.size);
    }),

  documentUploader: f({ pdf: { maxFileSize: "8MB" }, image: { maxFileSize: "4MB" } })
    .onUploadComplete(({ file }) => console.log(file.url)),
} satisfies FileRouter;
Enter fullscreen mode Exit fullscreen mode

React Component: Drop Zone

import { UploadButton, UploadDropzone } from "@uploadthing/react";
import type { uploadRouter } from "./uploadthing";

function UploadPage() {
  return (
    <div>
      {/* Simple button */}
      <UploadButton
        endpoint="imageUploader"
        onClientUploadComplete={(res) => {
          console.log("Files:", res.map(f => f.url));
        }}
        onUploadError={(error) => alert(error.message)}
      />

      {/* Drag and drop zone */}
      <UploadDropzone
        endpoint="csvUploader"
        onClientUploadComplete={(res) => {
          console.log("CSV uploaded:", res[0].url);
        }}
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

useUploadThing Hook: Full Control

import { useUploadThing } from "@uploadthing/react";

function CustomUpload() {
  const { startUpload, isUploading, permittedFileInfo } = useUploadThing("imageUploader", {
    onClientUploadComplete: (res) => console.log(res),
    onUploadError: (e) => console.error(e),
    onUploadProgress: (p) => console.log(`${p}%`),
  });

  return (
    <input
      type="file"
      onChange={async (e) => {
        const files = Array.from(e.target.files || []);
        await startUpload(files);
      }}
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

Server-Side: generateReactHelpers

import { generateReactHelpers } from "@uploadthing/react";
import type { uploadRouter } from "./uploadthing";

export const { useUploadThing, uploadFiles } = generateReactHelpers<typeof uploadRouter>();

// Upload from server
import { utapi } from "uploadthing/server";
const uploaded = await utapi.uploadFiles(file);
const url = uploaded.data.url;

// Delete files
await utapi.deleteFiles(["file-key-1", "file-key-2"]);

// Get file URLs
const urls = await utapi.getFileUrls(["key1", "key2"]);
Enter fullscreen mode Exit fullscreen mode

Upload scraped data files? My Apify tools + UploadThing = seamless data export.

Custom upload solution? Email spinov001@gmail.com

Top comments (0)