Choisissez un adaptateur de stockage pour les médias téléchargés. Une sauvegarde de base de données contient les métadonnées des médias, pas les fichiers stockés, sauvegardez donc le backend de stockage séparément.
Vue d’ensemble
| Stockage | À utiliser quand | Uploads signés |
|---|---|---|
| R2 binding | Le site tourne sur Cloudflare Workers | Non |
| S3 | Un site Node.js utilise AWS S3, l’API S3 de R2, MinIO ou un stockage compatible | Oui |
| Local | Un site Node.js a un volume persistant accessible en écriture | Non |
Cloudflare R2 binding
Utilisez l’adaptateur de binding R2 sur Cloudflare Workers. Le binding fournit l’accès au runtime, le site n’a donc pas besoin de clés d’accès R2.
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 de wrangler.jsonc |
publicUrl | string | URL publique optionnelle pour le bucket |
Installation
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 servir les médias depuis un bucket public, connectez un domaine personnalisé avec l’API Cloudflare, puis définissez son origine comme publicUrl. L’URL de développement r2.dev de Cloudflare est limitée en débit et n’est pas destinée au trafic de production.
storage: r2({
binding: "MEDIA",
publicUrl: "https://media.example.com",
});
Si le même bucket stocke des sauvegardes JSON automatiques, une origine de bucket publique peut exposer des objets sous backups/. Utilisez un bucket privé et la route média d’EmDash, ou restreignez l’origine publique aux objets média. Voir Sauvegardes.
Stockage compatible S3
L’adaptateur S3 fonctionne sur Node.js avec l’API S3 de Cloudflare R2, AWS S3, MinIO et les services compatibles.
La configuration suivante résout le endpoint, le bucket, les identifiants, la région et l’URL publique optionnelle depuis les variables S3_* au démarrage du processus Node.js :
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: s3(),
}),
],
});
Configuration
| Option | Type | Requis | Description |
|---|---|---|---|
endpoint | string | oui | URL du endpoint 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 (défaut : "auto") |
publicUrl | string | non | CDN ou URL publique optionnelle |
* accessKeyId et secretAccessKey doivent être fournis ensemble, ou tous deux omis.
Résoudre la config S3 depuis les variables d’environnement
Tout champ omis de s3({...}) est lu depuis la variable d’environnement S3_* correspondante au démarrage du processus. Cela vous permet de construire une image conteneur une 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 | 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. C’est une fonctionnalité Node uniquement.
Appeler s3() sans arguments lit chaque champ depuis les variables d’environnement S3_* :
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
// s3() sans arguments : tous les champs depuis les variables S3_*
storage: s3(),
// Ou mixer : remplacer un champ, le reste depuis l'environnement
// storage: s3({ publicUrl: "https://cdn.example.com" }),
}),
],
});
R2 via API S3
Utilisez l’adaptateur S3 sur Node.js quand des uploads signés directs vers R2 sont requis. Créez des identifiants API R2 à portée limitée avec l’API ou la CLI Cloudflare, puis définissez les variables runtime suivantes :
S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
S3_BUCKET=emdash-media
S3_ACCESS_KEY_ID=<r2-access-key-id>
S3_SECRET_ACCESS_KEY=<r2-secret-access-key>
S3_REGION=auto
S3_PUBLIC_URL=https://media.example.com
Gardez les vraies valeurs dans le gestionnaire de secrets de la plateforme d’hébergement Node.js. L’URL publique est optionnelle et ne remplace pas le endpoint de l’API S3 utilisé pour les uploads.
MinIO
Pointez les mêmes variables runtime vers MinIO. Définissez S3_ENDPOINT à l’origine de l’API MinIO, S3_BUCKET au nom du bucket, et les deux variables d’identifiants à une clé d’accès MinIO à portée limitée. Définissez S3_PUBLIC_URL uniquement quand cette origine sert les objets du bucket publiquement.
Système de fichiers local
Utilisez le stockage local pour le développement ou un serveur Node.js unique avec un disque persistant. Les fichiers sont stockés dans un répertoire sur ce 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 |
La baseUrl devrait correspondre au endpoint de fichier média d’EmDash (/_emdash/api/media/file) sauf si vous configurez un serveur de fichiers statiques personnalisé.
Utiliser un stockage séparé pour des environnements séparés
La configuration suivante utilise un répertoire local pendant le développement et R2 dans le build de production Cloudflare :
import emdash, { 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 supporte les URLs d’upload signées, permettant aux clients de télécharger directement vers le stockage sans passer par votre serveur. Cela améliore les performances pour les gros fichiers.
Les uploads signés sont automatiques lors de l’utilisation de l’adaptateur S3. L’interface admin les utilise quand disponibles.
Adaptateurs qui supportent les uploads signés :
- S3 (y compris R2 via API S3)
Adaptateurs qui ne supportent pas 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 de l’application.