AdminGuides

Cloud Storage Configuration Guide

Multi-Cloud Storage Configuration with One-Click Switching

Supported Services · Environment Variables · Usage · API Endpoints


🎯 Overview

This project supports multiple cloud storage providers. Switch between them by simply changing the CDN_MODE environment variable - no code changes required.


☁️ Supported Storage Services

CDN_MODEProviderUse CaseS3 Compatible
r2Cloudflare R2Global users, zero egress fees
s3AWS S3Global users, native AWS
aliyunAlibaba Cloud OSSChina users
qiniuQiniu Cloud StorageChina users

For global users, Cloudflare R2 is recommended - zero egress fees and global CDN acceleration. For users in China, Alibaba Cloud OSS is recommended.


🔧 Environment Variables

# Storage mode
CDN_MODE=r2

# R2 Configuration
R2_ACCOUNT_ID=your_cloudflare_account_id
R2_ACCESS_KEY_ID=your_r2_access_key_id
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_BUCKET_NAME=your_bucket_name
R2_PUBLIC_URL=https://your-custom-domain.com
# R2_ENDPOINT=https://xxx.r2.cloudflarestorage.com  # Optional, auto-generated by default

How to obtain:

  1. Log in to Cloudflare Dashboard
  2. Go to R2Create bucket
  3. Go to R2Manage R2 API TokensCreate API Token
  4. Select permissions: Object Read and Write
  5. Configure custom domain or use public access domain

2. AWS S3

# Storage mode
CDN_MODE=s3

# S3 Configuration
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your_aws_access_key_id
S3_SECRET_ACCESS_KEY=your_aws_secret_access_key
S3_BUCKET_NAME=your_bucket_name
S3_PUBLIC_URL=https://your-custom-domain.com  # Optional, defaults to S3 URL
# S3_ENDPOINT=https://s3.amazonaws.com  # Optional, for S3-compatible services

How to obtain:

  1. Log in to AWS Console
  2. Create an S3 bucket and configure public access
  3. Create an IAM user and obtain Access Key
  4. Configure IAM policy to allow S3 operations

3. Alibaba Cloud OSS

# Storage mode
CDN_MODE=aliyun

# Alibaba Cloud OSS Configuration
ALIYUN_OSS_REGION=oss-cn-hangzhou
ALIYUN_OSS_ACCESS_KEY_ID=your_aliyun_access_key_id
ALIYUN_OSS_ACCESS_KEY_SECRET=your_aliyun_access_key_secret
ALIYUN_OSS_BUCKET=your_bucket_name
ALIYUN_OSS_PUBLIC_URL=https://your-custom-domain.com  # Optional, defaults to OSS domain
# ALIYUN_OSS_INTERNAL=true  # Optional, enable for ECS internal network access

Common Region Codes:

Region CodeLocation
oss-cn-hangzhouEast China 1 (Hangzhou)
oss-cn-shanghaiEast China 2 (Shanghai)
oss-cn-qingdaoNorth China 1 (Qingdao)
oss-cn-beijingNorth China 2 (Beijing)
oss-cn-shenzhenSouth China 1 (Shenzhen)
oss-cn-hongkongHong Kong

For more regions, refer to Alibaba Cloud Documentation

How to obtain:

  1. Log in to Alibaba Cloud Console
  2. Create a Bucket and configure read/write permissions
  3. Create AccessKey in RAM Access Control
  4. Configure custom domain (optional)

4. Qiniu Cloud Storage

# Storage mode
CDN_MODE=qiniu

# Qiniu Configuration
QINIU_ACCESS_KEY=your_qiniu_access_key
QINIU_SECRET_KEY=your_qiniu_secret_key
QINIU_BUCKET=your_bucket_name
QINIU_PUBLIC_URL=https://your-cdn-domain.com
# QINIU_ZONE=z0  # Optional, storage zone

Storage Zone Codes:

CodeRegion
z0East China
z1North China
z2South China
na0North America
as0Southeast Asia

How to obtain:

  1. Log in to Qiniu Console
  2. Go to Object StorageCreate Space
  3. Get AccessKey/SecretKey in Key Management
  4. Bind CDN accelerated domain

📖 Usage

Switching Storage Services

Simply modify the CDN_MODE environment variable to switch storage services:

# Switch to Alibaba Cloud OSS
CDN_MODE=aliyun

# Switch to Cloudflare R2
CDN_MODE=r2

All upload and delete operations will automatically use the corresponding storage service - no code changes needed.

Using in Code

import {
  checkStorageConfig,
  uploadToStorage,
  deleteFromStorage,
  getStorageMode,
} from '@/lib/upload';

// Check configuration
const config = checkStorageConfig();
console.log('Current storage provider:', config.provider);

// Upload file
const result = await uploadToStorage({
  body: buffer,
  key: 'images/photo.jpg',
  contentType: 'image/jpeg',
});

// Delete file
await deleteFromStorage('images/photo.jpg');

📡 API Endpoints

Get Storage Configuration Info

GET /api/upload

Response Example:

{
  "configured": true,
  "provider": "aliyun",
  "types": {
    "image": { "maxSize": 5242880, "accept": ["image/jpeg", "image/png", "image/gif", "image/webp"] },
    "video": { "maxSize": 104857600, "accept": ["video/mp4", "video/webm"] },
    "document": { "maxSize": 10485760, "accept": ["application/pdf"] }
  }
}

Upload File

POST /api/upload
Content-Type: multipart/form-data

file: (binary)
type: image  # Optional: image, video, document
path: uploads/  # Optional: custom path prefix

Response Example:

{
  "success": true,
  "url": "https://your-domain.com/uploads/abc123.jpg",
  "key": "uploads/abc123.jpg"
}

📦 Installing Dependencies

Install the corresponding SDK based on the storage service you're using:

# R2/S3 (installed by default)
npm install @aws-sdk/client-s3

# Alibaba Cloud OSS
npm install ali-oss

# Qiniu Cloud
npm install qiniu

⚠️ Important Notes

Data Migration: After switching storage services, existing files will NOT be automatically migrated. Manual handling is required.

ItemDescription
Data MigrationExisting files won't auto-migrate when switching services
URL ChangesFile URLs will change after switching; update database references
Permission ConfigEnsure bucket has correct public read permissions
CORS ConfigIf uploading directly from frontend, configure bucket CORS rules

CORS Configuration Example

If you need to upload directly from the frontend to the storage service, configure CORS in the bucket:

{
  "AllowedOrigins": ["https://your-domain.com"],
  "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
  "AllowedHeaders": ["*"],
  "MaxAgeSeconds": 3000
}