dimah-s3v0.4.1
Custom backend

Multipart

multipart.init, signPart, listParts, complete, and abort — large-file uploads.

Multipart uploads split a large file into parts. Each part is uploaded with a presigned PUT; your backend orchestrates init, signing, completion, and abort.

Flow: initsignPart (per part) → complete or abort · listParts for resume

Init

Init payload

Same shape as the upload payload.

Prop

Type

import type { MultipartInitPayload } from "@dimah-s3/core";

MultipartInitResponse

Prop

Type

import type { MultipartInitResponse } from "@dimah-s3/core";

Sign part

Sign-part payload

Prop

Type

import type { MultipartSignPartPayload } from "@dimah-s3/core";

MultipartPartResponse

Prop

Type

import type { MultipartPartResponse } from "@dimah-s3/core";

List parts

List-parts payload

Prop

Type

import type { MultipartListPartsPayload } from "@dimah-s3/core";

MultipartListPartsResponse

Prop

Type

import type { MultipartListPartsResponse } from "@dimah-s3/core";

Complete

Complete payload

Prop

Type

import type { MultipartCompletePayload } from "@dimah-s3/core";

Complete response

Prop

Type

import type { MultipartCompleteResponse } from "@dimah-s3/core";

Abort

Abort payload

Same shape as list-parts payload.

Prop

Type

import type { MultipartAbortPayload } from "@dimah-s3/core";

Abort response

Prop

Type

import type { MultipartAbortResponse } from "@dimah-s3/core";

Example

@dimah-s3/server mounts multipart routes under /api/s3/presign/multipart/*.

lib/s3-api.ts (multipart)
import { defineApi } from "@dimah-s3/react";
import type { S3Api } from "@dimah-s3/core";

const base = "/api/files/presign/multipart";

async function apiFetch<T>(url: string, init?: RequestInit): Promise<T> {
  const res = await fetch(url, init);
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    throw new Error(body.message ?? res.statusText);
  }
  return res.json();
}

export const api = defineApi({
  multipart: {
    async init(payload) {
      return apiFetch(`${base}/init`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
    },

    async signPart(payload) {
      return apiFetch(`${base}/part`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
    },

    async listParts(payload) {
      const params = new URLSearchParams({
        key: payload.key,
        uploadId: payload.uploadId,
      });
      if (payload.bucket) params.set("bucket", payload.bucket);
      return apiFetch(`${base}/parts?${params}`);
    },

    async complete(payload) {
      return apiFetch(`${base}/complete`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
    },

    async abort(payload) {
      return apiFetch(`${base}/abort`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
    },
  },

  // upload, confirm, download, delete — see other pages
} satisfies Partial<S3Api> as S3Api);

On this page