Skip to Content
ProvidersCloudflare R2 Provider

Cloudflare R2 Provider

Cost-effective storage with zero egress fees.

Installation

pnpm add @fluxmedia/core @fluxmedia/r2 @aws-sdk/client-s3 @aws-sdk/lib-storage

R2 uses the S3-compatible API, so it requires @aws-sdk/client-s3.

Configuration

import { MediaUploader } from '@fluxmedia/core'; import { R2Provider } from '@fluxmedia/r2'; const uploader = new MediaUploader( new R2Provider({ accountId: 'your-cloudflare-account-id', bucket: 'my-bucket', accessKeyId: 'your-r2-access-key', secretAccessKey: 'your-r2-secret-key', publicUrl: 'https://cdn.example.com', // Optional: custom domain }) );

Configuration Options

OptionTypeRequiredDescription
accountIdstringYes*Cloudflare account ID
endpointstringYes*R2 endpoint (alternative to accountId)
bucketstringYesR2 bucket name
accessKeyIdstringYesR2 API token access key
secretAccessKeystringYesR2 API token secret key
publicUrlstringNoCustom public URL for the bucket

*Either accountId or endpoint is required.

Getting R2 Credentials

  1. Go to Cloudflare Dashboard  → R2
  2. Create a bucket
  3. Click “Manage R2 API Tokens”
  4. Create a token with read/write permissions
  5. Copy the Access Key ID and Secret Access Key

Basic Usage

const result = await uploader.upload(file, { folder: 'uploads', }); console.log(result.url); // https://cdn.example.com/uploads/file.jpg

Upload with Progress

const result = await uploader.upload(file, { folder: 'uploads', onProgress: (percent) => { console.log(`Upload progress: ${percent}%`); } });

Batch Uploads

const results = await uploader.uploadMultiple(files, { folder: 'batch-uploads', concurrency: 5, onBatchProgress: (completed, total) => { console.log(`Uploaded ${completed}/${total} files`); } });

Why R2?

  • Zero egress fees - Free outbound data transfer
  • S3-compatible - Easy migration from S3
  • Global distribution - Cloudflare’s edge network
  • Cost-effective - Only pay for storage and operations

Supported Features

R2 is storage-only:

uploader.supports('transformations.resize') // false uploader.supports('capabilities.signedUploads') // true uploader.supports('capabilities.multipartUpload') // true

Native SDK Access

Access the underlying S3-compatible client:

const client = uploader.provider.native; const { ListObjectsV2Command } = await import('@aws-sdk/client-s3'); const objects = await client.send(new ListObjectsV2Command({ Bucket: 'my-bucket' }));

Adding Transformations

Use Cloudflare Images  for image transformations, or consider Cloudinary for built-in support.

Environment Variables

CLOUDFLARE_ACCOUNT_ID=your-account-id R2_BUCKET=my-bucket R2_ACCESS_KEY_ID=your-access-key R2_SECRET_ACCESS_KEY=your-secret-key R2_PUBLIC_URL=https://cdn.example.com
Last updated on