dimah-s3v1.5.4
Providers

Providers

Configure Amazon S3, Cloudflare R2, MinIO, and other S3-compatible storage.

dimah-s3 talks to storage through the AWS SDK S3Client. Any service that speaks enough of the S3 API can work — Amazon S3, Cloudflare R2, MinIO, and similar backends.

S3-compatible is not the same as Amazon S3. Providers skip or ignore parts of the API. With a presign-first stack, those gaps show up quickly: the browser hits storage directly, so CORS, addressing, and the upload method have to match what the provider actually supports.

TopicWhy it matters
Presigned POST vs PUTDefault upload is POST. Some providers only accept PUT.
Object ACLacl: "public-read" needs real ACL support. Others use bucket policies or a public-access toggle.
Endpoint & addressingCustom endpoints often need endpoint, and sometimes forcePathStyle: true.
CORSBrowser uploads hit storage directly. The bucket must allow your origin, methods, and headers.
Public URLsPublic reads may use a CDN, a custom domain, or *.r2.dev — not object ACL.

Wire the shared client once in Quickstart. Use the guides below only for the extras that defaults do not cover.

Comparison

AWS S3Cloudflare R2MinIO
Presigned POSTYesNoYes
Presigned PUTYesYes (required)Yes
Object ACLYesIgnoredUse policies
Custom endpointOptionalRequiredRequired
forcePathStyleUsually offOffRequired

Configuration

import { dimahS3, route } from "@dimah-s3/server";

export const s3 = dimahS3({
  client: awsS3,
  bucket: process.env.S3_BUCKET!,
  routes: {
    avatar: route({
      upload: { method: "PUT" },
    }),
  },
});

The default upload method is POST. Switch to PUT when the provider has no Presigned POST (R2 is the usual case). ACL on confirm comes from upload.acl / object — there is no GetObjectAcl lookup.

Client hooks and @dimah-s3/ui read method from the presign response. Change it on the server only.

Guides

On this page