Aviary
Packages

@dudousxd/nestjs-media-disk-s3

The S3 driver — presigned URLs + native multipart, works with any S3-compatible endpoint.

A StorageDriver over Amazon S3 and any S3-compatible service (MinIO, Cloudflare R2, Backblaze B2, …). It's a POJO that receives an S3Client — your app owns the client, region, and credentials.

import { S3Driver } from '@dudousxd/nestjs-media-disk-s3';
import { S3Client } from '@aws-sdk/client-s3';

new S3Driver({
  client: new S3Client({ region: 'us-east-1' }),
  bucket: 'app-uploads',
  keyPrefix: 'uploads',           // optional — prepended to every key
  publicBaseUrl: 'https://cdn…',  // optional — enables url() (e.g. a CloudFront domain)
});

Capabilities

{ presign: true, multipart: true, publicUrls: !!publicBaseUrl, list: true }
  • temporaryUrl(path, ttl) returns a signed GET URL (via @aws-sdk/s3-request-presigner).
  • url(path) returns ${publicBaseUrl}/${key} when set, else throws.
  • presign + multipart are what uploadMode: 'auto' reads to choose the direct (presigned multipart) upload path.

Multipart presign surface

Because capabilities.multipart is true, the driver also implements the optional MultipartUploadDriver add-on that backs direct-to-S3 presigned multipart uploads:

createMultipartUpload(path, options?): Promise<{ uploadId: string }>;
presignUploadPart(path, uploadId, partNumber, expiresInSeconds): Promise<string>; // PUT URL
completeMultipartUpload(path, uploadId, parts): Promise<void>;                     // parts: { partNumber, etag }[]
abortMultipartUpload(path, uploadId): Promise<void>;

You rarely call these directly — DirectUploadManager (and the MediaModule.direct controller) drives them. createMultipartUpload maps to S3's CreateMultipartUpload, presignUploadPart signs an UploadPart command, and completeMultipartUpload stitches the collected ETags server-side.

S3-compatible endpoints

Point the client at any compatible service:

new S3Client({
  region: 'auto',
  endpoint: 'https://<account>.r2.cloudflarestorage.com',
  forcePathStyle: true,           // MinIO and some others need this
  credentials: { accessKeyId, secretAccessKey },
});

Verified against real S3

The driver's behavior is validated by the shared conformance suite running against a real MinIO server (testcontainers) — not just mocks — so put/get/stream/copy/move/size/delete and error semantics match a real backend. See -testing.

Peer dependencies

@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner (v3), plus @dudousxd/nestjs-media-core.

On this page