Choisir le stockage des médias

Sur cette page

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 quandUploads signés
R2 bindingLe site tourne sur Cloudflare WorkersNon
S3Un site Node.js utilise AWS S3, l’API S3 de R2, MinIO ou un stockage compatibleOui
LocalUn site Node.js a un volume persistant accessible en écritureNon

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

OptionTypeDescription
bindingstringNom du binding R2 de wrangler.jsonc
publicUrlstringURL 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

OptionTypeRequisDescription
endpointstringouiURL du endpoint S3
bucketstringouiNom du bucket
accessKeyIdstringnon*Clé d’accès
secretAccessKeystringnon*Clé secrète
regionstringnonRégion (défaut : "auto")
publicUrlstringnonCDN 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’environnementChampNotes
S3_ENDPOINTendpointDoit être une URL http/https valide
S3_BUCKETbucket
S3_ACCESS_KEY_IDaccessKeyId
S3_SECRET_ACCESS_KEYsecretAccessKey
S3_REGIONregionDéfaut : "auto"
S3_PUBLIC_URLpublicUrlPré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

OptionTypeDescription
directorystringChemin du répertoire de stockage
baseUrlstringURL 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.