O EmDash armazena mídia enviada (imagens, documentos, vídeos) em um backend de armazenamento configurável. Escolha com base na sua plataforma de deploy e requisitos.
Visão geral
| Armazenamento | Ideal para | Recursos |
|---|---|---|
| R2 Binding | Cloudflare Workers | Zero configuração, rápido |
| S3 | Qualquer plataforma | Uploads assinados, suporte CDN |
| Local | Desenvolvimento | Armazenamento de arquivos simples |
Cloudflare R2 (Binding)
Use bindings R2 para a integração mais rápida ao fazer deploy no Cloudflare Workers.
import emdash from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
storage: r2({ binding: "MEDIA" }),
}),
],
});
Configuração
| Opção | Tipo | Descrição |
|---|---|---|
binding | string | Nome do binding R2 em wrangler.jsonc |
publicUrl | string | URL pública do bucket (opcional) |
Configuração inicial
Adicione o binding R2 à sua configuração do Wrangler:
wrangler.jsonc
{
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "emdash-media"
}
]
} wrangler.toml
[[r2_buckets]]
binding = "MEDIA"
bucket_name = "emdash-media" Acesso público
Para URLs de mídia públicas, habilite o acesso público no seu bucket R2:
- Painel do Cloudflare > R2 > seu bucket
- Habilitar acesso público em Configurações
- Adicionar a URL pública à sua configuração:
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev",
});
Armazenamento compatível com S3
O adaptador S3 funciona com Cloudflare R2 (via API S3), MinIO e outros serviços compatíveis com 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
}),
}),
],
});
Configuração
| Opção | Tipo | Obrigatório | Descrição |
|---|---|---|---|
endpoint | string | sim | URL do endpoint S3 |
bucket | string | sim | Nome do bucket |
accessKeyId | string | não* | Chave de acesso |
secretAccessKey | string | não* | Chave secreta |
region | string | não | Região (padrão: "auto") |
publicUrl | string | não | URL CDN ou pública (opcional) |
* accessKeyId e secretAccessKey devem ser fornecidos juntos, ou ambos omitidos.
Resolução da configuração S3 a partir de variáveis de ambiente
Qualquer campo omitido em s3({...}) é lido da variável de ambiente S3_* correspondente
quando o processo inicia. Isso permite construir uma imagem de contêiner uma vez e injetar
credenciais na inicialização sem reconstruir. Valores explícitos em s3({...}) sempre têm
prioridade sobre variáveis de ambiente.
| Variável de ambiente | Campo | Notas |
|---|---|---|
S3_ENDPOINT | endpoint | Deve ser uma URL http/https válida |
S3_BUCKET | bucket | |
S3_ACCESS_KEY_ID | accessKeyId | |
S3_SECRET_ACCESS_KEY | secretAccessKey | |
S3_REGION | region | Padrão "auto" |
S3_PUBLIC_URL | publicUrl | Prefixo CDN opcional |
As variáveis de ambiente são lidas de process.env quando o processo inicia. Este é um recurso exclusivo do 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 API S3
Use credenciais S3 com R2 para recursos como URLs de upload assinadas:
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",
});
Gere credenciais de API R2 no painel do Cloudflare em 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",
});
Sistema de arquivos local
Use armazenamento local para desenvolvimento. Os arquivos são armazenados em um diretório no disco.
import emdash, { local } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
}),
],
});
Configuração
| Opção | Tipo | Descrição |
|---|---|---|
directory | string | Caminho do diretório de armazenamento |
baseUrl | string | URL base para servir arquivos |
O baseUrl deve corresponder ao endpoint de arquivos de mídia do EmDash (/_emdash/api/media/file) a menos que você configure um servidor de arquivos estáticos personalizado.
Configuração baseada em ambiente
Alterne backends de armazenamento com base no ambiente:
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 assinados
O adaptador S3 suporta URLs de upload assinadas, permitindo que clientes façam upload diretamente para o armazenamento sem passar pelo seu servidor. Isso melhora o desempenho para arquivos grandes.
Uploads assinados são automáticos ao usar o adaptador S3. A interface de administração os utiliza quando disponíveis.
Adaptadores que suportam uploads assinados:
- S3 (incluindo R2 via API S3)
Adaptadores que não suportam uploads assinados:
- R2 binding (use o adaptador S3 com credenciais R2 em vez disso)
- Local
Interface de armazenamento
Todos os adaptadores de armazenamento implementam a mesma 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;
}
Essa consistência permite trocar backends de armazenamento sem alterar o código da aplicação.