CodingNic

EPUB Upload & Storage

Build the EPUB Upload Endpoint

EPUB Upload & Storage 20 min read

Build the EPUB Upload Endpoint

Build the EPUB Upload Endpoint

Task

Create an authenticated upload endpoint that accepts an EPUB file and creates the matching Book record.

Route

Create:

text
app/api/books/upload/route.ts

Read the multipart form:

ts
const formData = await request.formData();
const file = formData.get("file");

if (!(file instanceof File)) {
  return Response.json({ error: "EPUB file is required" }, { status: 400 });
}

Convert it to a buffer for the storage client:

ts
const body = Buffer.from(await file.arrayBuffer());

Generate an object key scoped to the current user:

ts
const key = `users/${user.id}/books/${crypto.randomUUID()}.epub`;

Then upload:

ts
await storage.send(
  new PutObjectCommand({
    Bucket: bucket,
    Key: key,
    Body: body,
    ContentType: "application/epub+zip",
  }),
);

Create the Book record only after the upload succeeds.

If database creation fails after the object is stored, delete the object as part of the failure cleanup.

Test

Upload a small EPUB through the prepared Library upload UI.

Confirm:

  • an object appears in SeaweedFS
  • a Book record appears in PostgreSQL
  • the Book points to the correct storage key

Checkpoint

An authenticated Readly user can upload a real EPUB and create a persistent Book record.