Escolha um adaptador de armazenamento para mídia carregada. Um backup de banco de dados contém metadados de mídia, não os arquivos armazenados, então faça backup do backend de armazenamento separadamente.
Visão geral
| Armazenamento | Quando usar | Upload assinado |
|---|---|---|
| R2 binding | O site roda no Cloudflare Workers | Não |
| S3 | Um site Node.js usa AWS S3, API S3 do R2, MinIO ou armazenamento compatível | Sim |
| Local | Um site Node.js tem um volume persistente gravável | Não |
Cloudflare R2 binding
Use o adaptador de binding R2 no Cloudflare Workers. O binding fornece acesso em tempo de execução, então o site não precisa de chaves de acesso R2.
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 do wrangler.jsonc |
publicUrl | string | URL pública opcional para o bucket |
Setup
Adicione o binding R2 à sua configuração 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 servir mídia de um bucket público, conecte um domínio personalizado com a API Cloudflare, depois defina sua origem como publicUrl. A URL de desenvolvimento r2.dev do Cloudflare tem limites de taxa e não é destinada para tráfego de produção.
storage: r2({
binding: "MEDIA",
publicUrl: "https://media.example.com",
});
Se o mesmo bucket armazena backups JSON automáticos, uma origem de bucket público pode expor objetos sob backups/. Use um bucket privado e a rota de mídia do EmDash, ou restrinja a origem pública a objetos de mídia. Veja Backups.
Armazenamento compatível com S3
O adaptador S3 funciona no Node.js com a API S3 do Cloudflare R2, AWS S3, MinIO e serviços compatíveis.
A seguinte configuração resolve endpoint, bucket, credenciais, região e URL pública opcional das variáveis S3_* na inicialização do processo Node.js:
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
storage: s3(),
}),
],
});
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 | CDN opcional ou URL pública |
* Tanto accessKeyId quanto secretAccessKey devem ser fornecidos juntos, ou ambos omitidos.
Resolver config S3 de variáveis de ambiente
Todo campo omitido de s3({...}) é lido da variável de ambiente S3_* correspondente na inicialização do processo. Isso permite construir uma imagem de container uma vez e injetar credenciais na inicialização sem reconstruir. Valores explícitos em s3({...}) sempre têm precedência 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 na inicialização do processo. Esta é uma funcionalidade apenas do Node.
Chamar s3() sem argumentos lê todos os campos das variáveis de ambiente S3_*:
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
// s3() sem argumentos: todos os campos das variáveis S3_*
storage: s3(),
// Ou misto: sobrescrever um campo, resto do ambiente
// storage: s3({ publicUrl: "https://cdn.example.com" }),
}),
],
});
R2 via API S3
Use o adaptador S3 no Node.js quando uploads assinados diretos para R2 são necessários. Crie credenciais de API R2 com escopo limitado com a API ou CLI Cloudflare, depois defina as seguintes variáveis de 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
Mantenha os valores reais no gerenciador de secrets da plataforma de hospedagem Node.js. A URL pública é opcional e não substitui o endpoint da API S3 usado para uploads.
MinIO
Aponte as mesmas variáveis de runtime para o MinIO. Defina S3_ENDPOINT como a origem da API MinIO, S3_BUCKET como o nome do bucket, e as duas variáveis de credenciais como uma chave de acesso MinIO com escopo limitado. Defina S3_PUBLIC_URL apenas quando essa origem serve objetos do bucket publicamente.
Sistema de arquivos local
Use armazenamento local para desenvolvimento ou um único servidor Node.js com disco persistente. Os arquivos são armazenados em um diretório nesse 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 arquivo de mídia do EmDash (/_emdash/api/media/file) a menos que você configure um servidor de arquivos estáticos personalizado.
Usar armazenamentos separados para ambientes separados
A seguinte configuração usa um diretório local durante o desenvolvimento e R2 no build de produção 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 assinados
O adaptador S3 suporta URLs de upload assinados, permitindo que clientes façam upload diretamente para o armazenamento sem passar pelo servidor. Isso melhora o desempenho para arquivos grandes.
Uploads assinados são automáticos usando o adaptador S3. A interface admin os usa 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.