Options de stockage

Sur cette page

EmDash stocke les médias uploadés (images, documents, vidéos) dans un backend de stockage configurable. Choisissez en fonction de votre plateforme de déploiement et de vos besoins.

Vue d’ensemble

StockageIdéal pourCaractéristiques
R2 BindingCloudflare WorkersZéro configuration, rapide
S3Toute plateformeUploads signés, support CDN
LocalDéveloppementStockage fichiers simple

Cloudflare R2 (Binding)

Utilisez les bindings R2 pour l’intégration la plus rapide lors du déploiement sur Cloudflare Workers.

import emdash from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

export default defineConfig({
	integrations: [
		emdash({
			storage: r2({ binding: "MEDIA" }),
		}),
	],
});

Configuration

OptionTypeDescription
bindingstringNom du binding R2 dans wrangler.jsonc
publicUrlstringURL publique du bucket (optionnel)

Mise en place

Ajoutez le binding R2 à votre configuration Wrangler :

wrangler.jsonc

{
  "r2_buckets": [
    {
      "binding": "MEDIA",
      "bucket_name": "emdash-media"
    }
  ]
}

wrangler.toml

[[r2_buckets]]
binding = "MEDIA"
bucket_name = "emdash-media"

Accès public

Pour des URL médias publiques, activez l’accès public sur votre bucket R2 :

  1. Tableau de bord Cloudflare > R2 > votre bucket
  2. Activez l’accès public dans les paramètres
  3. Ajoutez l’URL publique à votre configuration :
storage: r2({
	binding: "MEDIA",
	publicUrl: "https://pub-xxxx.r2.dev",
});

Stockage compatible S3

L’adaptateur S3 fonctionne avec Cloudflare R2 (via l’API S3), MinIO et d’autres services compatibles S3.

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			storage: s3({
				endpoint: process.env.S3_ENDPOINT,
				bucket: process.env.S3_BUCKET,
				accessKeyId: process.env.S3_ACCESS_KEY_ID,
				secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
				region: "auto", // Optional, defaults to "auto"
				publicUrl: process.env.S3_PUBLIC_URL, // Optional CDN URL
			}),
		}),
	],
});

Configuration

OptionTypeRequisDescription
endpointstringouiURL du point de terminaison S3
bucketstringouiNom du bucket
accessKeyIdstringnon*Clé d’accès
secretAccessKeystringnon*Clé secrète
regionstringnonRégion (par défaut : "auto")
publicUrlstringnonURL CDN ou publique (optionnel)

* accessKeyId et secretAccessKey doivent être fournis ensemble, ou tous deux omis.

Résolution de la configuration S3 à partir des variables d’environnement

Tout champ omis dans s3({...}) est lu à partir de la variable d’environnement S3_* correspondante au démarrage du processus. Cela vous permet de construire une image de conteneur une seule fois et d’injecter les identifiants au démarrage sans reconstruction. Les valeurs explicites dans s3({...}) ont toujours priorité sur les variables d’environnement.

Variable d’environnementChampNotes
S3_ENDPOINTendpointDoit être une URL http/https valide
S3_BUCKETbucket
S3_ACCESS_KEY_IDaccessKeyId
S3_SECRET_ACCESS_KEYsecretAccessKey
S3_REGIONregionPar défaut "auto"
S3_PUBLIC_URLpublicUrlPréfixe CDN optionnel

Les variables d’environnement sont lues depuis process.env au démarrage du processus. Cette fonctionnalité est réservée à Node.

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			// s3() with no args: all fields from S3_* environment variables
			storage: s3(),

			// Or mix: override one field, rest from environment
			// storage: s3({ publicUrl: "https://cdn.example.com" }),
		}),
	],
});

R2 via l’API S3

Utilisez des identifiants S3 avec R2 pour des fonctionnalités comme les URL d’upload signées :

storage: s3({
	endpoint: "https://<account-id>.r2.cloudflarestorage.com",
	bucket: "emdash-media",
	accessKeyId: process.env.R2_ACCESS_KEY_ID,
	secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
	publicUrl: "https://pub-xxxx.r2.dev",
});

Générez des identifiants API R2 dans le tableau de bord Cloudflare sous R2 > Manage R2 API Tokens.

MinIO

storage: s3({
	endpoint: "https://minio.example.com",
	bucket: "emdash-media",
	accessKeyId: process.env.MINIO_ACCESS_KEY,
	secretAccessKey: process.env.MINIO_SECRET_KEY,
	publicUrl: "https://minio.example.com/emdash-media",
});

Système de fichiers local

Utilisez le stockage local pour le développement. Les fichiers sont stockés dans un répertoire sur disque.

import emdash, { local } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			storage: local({
				directory: "./uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
		}),
	],
});

Configuration

OptionTypeDescription
directorystringChemin du répertoire de stockage
baseUrlstringURL de base pour servir les fichiers

Le baseUrl doit correspondre au point de terminaison média d’EmDash (/_emdash/api/media/file) sauf si vous configurez un serveur de fichiers statiques personnalisé.

Configuration selon l’environnement

Changez de backend de stockage selon l’environnement :

import emdash, { s3, local } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

const storage = import.meta.env.PROD
	? r2({ binding: "MEDIA" })
	: local({
			directory: "./uploads",
			baseUrl: "/_emdash/api/media/file",
		});

export default defineConfig({
	integrations: [emdash({ storage })],
});

Uploads signés

L’adaptateur S3 prend en charge les URL d’upload signées, permettant aux clients d’uploader directement vers le stockage sans passer par votre serveur. Cela améliore les performances pour les fichiers volumineux.

Les uploads signés sont automatiques avec l’adaptateur S3. L’interface d’administration les utilise lorsqu’ils sont disponibles.

Adaptateurs qui prennent en charge les uploads signés :

  • S3 (y compris R2 via l’API S3)

Adaptateurs qui ne prennent pas en charge les uploads signés :

  • R2 binding (utilisez l’adaptateur S3 avec des identifiants R2 à la place)
  • Local

Interface de stockage

Tous les adaptateurs de stockage implémentent la même interface :

interface Storage {
	upload(options: {
		key: string;
		body: Buffer | Uint8Array | ReadableStream;
		contentType: string;
	}): Promise<UploadResult>;

	download(key: string): Promise<DownloadResult>;
	delete(key: string): Promise<void>;
	exists(key: string): Promise<boolean>;
	list(options?: ListOptions): Promise<ListResult>;
	getSignedUploadUrl(options: SignedUploadOptions): Promise<SignedUploadUrl>;
	getPublicUrl(key: string): string;
}

Cette cohérence permet de changer de backend de stockage sans modifier le code applicatif.