Scegliere lo storage dei media

In questa pagina

Scegli un adattatore di storage per i media caricati. Un backup del database contiene i metadati dei media, non i file archiviati, quindi fai il backup del backend di storage separatamente.

Panoramica

StorageUsalo quandoUpload firmati
R2 bindingIl sito gira su Cloudflare WorkersNo
S3Un sito Node.js usa AWS S3, l’API S3 di R2, MinIO o storage compatibile
LocaleUn sito Node.js ha un volume persistente scrivibileNo

Cloudflare R2 binding

Usa l’adattatore di binding R2 su Cloudflare Workers. Il binding fornisce l’accesso a runtime, quindi il sito non necessita di chiavi di accesso R2.

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

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

Configurazione

OpzioneTipoDescrizione
bindingstringNome del binding R2 da wrangler.jsonc
publicUrlstringURL pubblica opzionale per il bucket

Setup

Aggiungi il binding R2 alla tua configurazione Wrangler:

wrangler.jsonc

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

wrangler.toml

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

Accesso pubblico

Per servire media da un bucket pubblico, connetti un dominio personalizzato con l’API Cloudflare, poi imposta la sua origine come publicUrl. L’URL di sviluppo r2.dev di Cloudflare ha limiti di velocità e non è pensata per il traffico di produzione.

storage: r2({
	binding: "MEDIA",
	publicUrl: "https://media.example.com",
});

Se lo stesso bucket archivia backup JSON automatici, un’origine di bucket pubblico può esporre oggetti sotto backups/. Usa un bucket privato e la route media di EmDash, o limita l’origine pubblica agli oggetti media. Vedi Backup.

Storage compatibile S3

L’adattatore S3 funziona su Node.js con l’API S3 di Cloudflare R2, AWS S3, MinIO e servizi compatibili.

La seguente configurazione risolve endpoint, bucket, credenziali, regione e URL pubblica opzionale dalle variabili S3_* all’avvio del processo Node.js:

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

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

Configurazione

OpzioneTipoRichiestoDescrizione
endpointstringURL endpoint S3
bucketstringNome del bucket
accessKeyIdstringno*Chiave di accesso
secretAccessKeystringno*Chiave segreta
regionstringnoRegione (default: "auto")
publicUrlstringnoCDN o URL pubblica opzionale

* Sia accessKeyId che secretAccessKey devono essere forniti insieme, o entrambi omessi.

Risolvere la config S3 dalle variabili d’ambiente

Ogni campo omesso da s3({...}) viene letto dalla variabile d’ambiente S3_* corrispondente all’avvio del processo. Questo permette di costruire un’immagine container una volta e iniettare le credenziali all’avvio senza ricostruire. I valori espliciti in s3({...}) hanno sempre la precedenza sulle variabili d’ambiente.

Variabile d’ambienteCampoNote
S3_ENDPOINTendpointDeve essere un URL http/https valido
S3_BUCKETbucket
S3_ACCESS_KEY_IDaccessKeyId
S3_SECRET_ACCESS_KEYsecretAccessKey
S3_REGIONregionDefault: "auto"
S3_PUBLIC_URLpublicUrlPrefisso CDN opzionale

Le variabili d’ambiente vengono lette da process.env all’avvio del processo. Questa è una funzionalità solo Node.

Chiamare s3() senza argomenti legge ogni campo dalle variabili d’ambiente S3_*:

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

export default defineConfig({
	integrations: [
		emdash({
			// s3() senza argomenti: tutti i campi dalle variabili S3_*
			storage: s3(),

			// O mischiare: sovrascrivere un campo, il resto dall'ambiente
			// storage: s3({ publicUrl: "https://cdn.example.com" }),
		}),
	],
});

R2 via API S3

Usa l’adattatore S3 su Node.js quando sono richiesti upload firmati diretti a R2. Crea credenziali API R2 con ambito limitato con l’API o CLI Cloudflare, poi imposta le seguenti variabili runtime:

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

Conserva i valori reali nel gestore dei segreti della piattaforma di hosting Node.js. L’URL pubblica è opzionale e non sostituisce l’endpoint dell’API S3 usato per gli upload.

MinIO

Punta le stesse variabili runtime a MinIO. Imposta S3_ENDPOINT all’origine dell’API MinIO, S3_BUCKET al nome del bucket, e le due variabili di credenziali a una chiave di accesso MinIO con ambito limitato. Imposta S3_PUBLIC_URL solo quando quell’origine serve gli oggetti del bucket pubblicamente.

Sistema di file locale

Usa lo storage locale per lo sviluppo o un singolo server Node.js con disco persistente. I file sono archiviati in una directory su quel disco.

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

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

Configurazione

OpzioneTipoDescrizione
directorystringPercorso directory per lo storage
baseUrlstringURL base per servire i file

La baseUrl dovrebbe corrispondere all’endpoint file media di EmDash (/_emdash/api/media/file) a meno che non configuri un server di file statici personalizzato.

Usare storage separati per ambienti separati

La seguente configurazione usa una directory locale durante lo sviluppo e R2 nel build di produzione 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 })],
});

Upload firmati

L’adattatore S3 supporta URL di upload firmati, permettendo ai client di caricare direttamente nello storage senza passare dal server. Questo migliora le prestazioni per file grandi.

Gli upload firmati sono automatici usando l’adattatore S3. L’interfaccia admin li usa quando disponibili.

Adattatori che supportano upload firmati:

  • S3 (incluso R2 via API S3)

Adattatori che non supportano upload firmati:

  • R2 binding (usa l’adattatore S3 con credenziali R2 invece)
  • Locale

Interfaccia di storage

Tutti gli adattatori di storage implementano la stessa interfaccia:

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;
}

Questa coerenza permette di cambiare backend di storage senza modificare il codice dell’applicazione.