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
| Stockage | Idéal pour | Caractéristiques |
|---|---|---|
| R2 Binding | Cloudflare Workers | Zéro configuration, rapide |
| S3 | Toute plateforme | Uploads signés, support CDN |
| Local | Développement | Stockage 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
| Option | Type | Description |
|---|---|---|
binding | string | Nom du binding R2 dans wrangler.jsonc |
publicUrl | string | URL 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 :
- Tableau de bord Cloudflare > R2 > votre bucket
- Activez l’accès public dans les paramètres
- 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
| Option | Type | Requis | Description |
|---|---|---|---|
endpoint | string | oui | URL du point de terminaison S3 |
bucket | string | oui | Nom du bucket |
accessKeyId | string | non* | Clé d’accès |
secretAccessKey | string | non* | Clé secrète |
region | string | non | Région (par défaut : "auto") |
publicUrl | string | non | URL 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’environnement | Champ | Notes |
|---|---|---|
S3_ENDPOINT | endpoint | Doit être une URL http/https valide |
S3_BUCKET | bucket | |
S3_ACCESS_KEY_ID | accessKeyId | |
S3_SECRET_ACCESS_KEY | secretAccessKey | |
S3_REGION | region | Par défaut "auto" |
S3_PUBLIC_URL | publicUrl | Pré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
| Option | Type | Description |
|---|---|---|
directory | string | Chemin du répertoire de stockage |
baseUrl | string | URL 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.