Campos de upload de arquivos
Um campo de arquivo é uma propriedade string comum com um bloco storage. A
coluna armazena texto — a chave do objeto no bucket, ou sua URL se você solicitar
isso — e o bloco indica para onde os bytes vão e o que o formulário aceitará.
Essa divisão importa mais do que parece. A maior parte do storage é lida pelo
uploader do painel de administração a caminho da API, portanto, uma gravação que não venha
de um formulário não passa por ele — essas opções trazem a indicação abaixo. As duas que
decidem o que um arquivo pode ser, maxSize e acceptedFiles, são a exceção:
o servidor as verifica a cada upload para o storagePath da propriedade.
Um arquivo
Seção intitulada “Um arquivo”avatar: { type: "string", name: "Main image", storage: { storagePath: "avatars", acceptedFiles: ["image/*"], maxSize: 2 * 1024 * 1024 }}Vários arquivos
Seção intitulada “Vários arquivos”Um array da mesma coisa. O bloco storage é movido para of, pois
descreve cada elemento em vez da lista:
images: { type: "array", name: "Images", of: { type: "string", storage: { storagePath: "images", acceptedFiles: ["image/*"] } }}Opções de storage
Seção intitulada “Opções de storage”Tudo dentro de storage.
| Propriedade | Tipo | Descrição |
|---|---|---|
storagePath |
string | function |
Obrigatório. Onde no bucket o arquivo é armazenado. Uma string com placeholders — {file}, {file.name}, {file.ext}, {rand}, {entityId}, {propertyKey}, {path} — ou uma função do contexto do upload. Apenas formulário de admin — não imposto pela API ou banco de dados: é o uploader do painel que o resolve, e client.storage.upload() define sua própria chave. Um caminho em string também é onde o servidor aplica, a cada upload, o maxSize e o acceptedFiles desta propriedade |
fileName |
string | function |
O nome de arquivo do objeto enviado, com os mesmos placeholders. Apenas formulário de admin — não imposto pela API ou banco de dados. |
storageSource |
string |
Qual bucket registrado utilizar, quando um projeto tiver mais de um. O identificador bucket("media") também funciona aqui |
public |
boolean |
Armazena sob o prefixo público e serve por meio de uma URL estável, sem token e armazenável em cache. false por padrão, o que significa objetos privados e URLs assinadas de curta duração |
acceptedFiles |
FileType[] |
Tipos MIME que esta propriedade aceita. O formato com asterisco funciona — image/*. Imposto pelo servidor para todo upload destinado ao storagePath da propriedade — consulte O que o servidor verifica |
maxSize |
number |
Maior arquivo aceito, em bytes. Imposto pelo servidor, assim como acceptedFiles, tanto em uploads comuns quanto nos retomáveis |
metadata |
Record<string, unknown> |
Metadados do objeto para armazenar junto com o arquivo |
includeBucketUrl |
boolean |
Grava s3://my-bucket/path/to/file.png na coluna em vez de path/to/file.png. false por padrão |
storeUrl |
boolean |
Grava a URL de download na coluna em vez da chave. false por padrão, e vale a pena manter assim: uma URL que carrega um token para de funcionar quando o token expira, e a referência original é perdida |
imageResize |
ImageResize |
Redimensiona e corta antes do upload, para image/jpeg, image/png e image/webp. Apenas formulário de admin — não imposto pela API ou banco de dados. |
processFile |
(file: File) => Promise<File> |
Transforma o arquivo antes de ser enviado. Executa no navegador. Apenas formulário de admin — não imposto pela API ou banco de dados. |
postProcess |
(pathOrUrl: string) => Promise<string> |
Transforma o caminho ou URL resolvido antes de ser salvo. Executa no navegador. Apenas formulário de admin — não imposto pela API ou banco de dados. |
previewUrl |
(fileName: string) => string |
Gera a URL de pré-visualização, para quando o endereço real do arquivo não for o valor do campo. Apenas formulário de admin — não imposto pela API ou banco de dados. |
Redimensionamento
Seção intitulada “Redimensionamento”O imageResize aceita maxWidth e maxHeight em pixels, um mode de
"contain" (reduzir para caber, o padrão) ou "cover" (preencher os limites e
cortar), um format de "original", "jpeg", "png" ou "webp", e uma
quality entre 0 e 100 para formatos com perdas — 80 por padrão. Isso ocorre no
navegador, antes de os bytes serem enviados, de modo que um upload que não tenha vindo do
painel seja armazenado em seu tamanho original.
O que o servidor verifica
Seção intitulada “O que o servidor verifica”Antes, maxSize e acceptedFiles eram impostos por exatamente uma coisa: o
navegador. A rota de upload conhecia apenas um limite global de tamanho e nada sobre a
propriedade a que o arquivo se destinava; assim, um curl -F file=@payload.exe
ignorando o seletor colocava um executável de 40 MB no bucket de avatares e a
configuração que dizia o contrário nunca era consultada.
Ambos agora são verificados pelo servidor em relação a onde o arquivo é gravado. Na
0.23 eles são verificados apenas em relação à propriedade que um upload nomeia, e um upload
que não nomeia nenhuma atende apenas ao limite da própria fonte.
O storagePath de uma propriedade é para onde vão os seus arquivos, então é
também onde valem os seus limites: todo upload cuja chave é um arquivo
diretamente sob esse caminho — do painel, do client.storage.putObject, de um
upload retomável, do navegador de storage do Studio ou do curl — precisa
atendê-los, especifique ou não a propriedade, na fonte de storage da própria
propriedade. Os placeholders correspondem ao que o painel preencheria:
{entityId}, {rand}, {file} e semelhantes representam um segmento do
caminho, {path} qualquer número deles. O caminho de uma propriedade com
public: true fica sob public/.
- Várias propriedades compartilhando um mesmo caminho: um arquivo aceito por uma delas é aceito.
- Um upload que também especifica sua propriedade (
collection+property, comoputObject({ context })os envia) também é submetido às regras dessa propriedade. Especificar uma propriedade mais permissiva não libera o caminho de uma mais restritiva. Os uploads do painel (campos de arquivo, células de tabela e imagens markdown) sempre a especificam. - Um
storagePathescrito como função não pode ser lido sem executá-lo, então não tem regra no servidor: esses limites só valem para uploads que especificam a propriedade, o que os do painel fazem. - Um caminho que nenhuma propriedade reivindica fica sujeito apenas ao limite
da própria fonte (
STORAGE_MAX_FILE_SIZE).
Imagens em um campo markdown
Seção intitulada “Imagens em um campo markdown”Uma propriedade markdown (admin.markdown: true) com um bloco storage aceita
uploads de imagem em seu editor. O texto armazena cada imagem como uma
referência de storage —  — e não
como uma URL: a URL de um arquivo privado carrega um token de download que
expira em minutos, e é o texto que é salvo. O editor e as pré-visualizações do
painel de administração trocam cada referência por uma URL nova ao exibi-la; um
site que renderiza o campo faz o mesmo com
resolveStorageReferences(text, client) — consulte
Arquivos dentro de texto.
Textos salvos antes das referências armazenam as próprias URLs de download, com tokens
expirados. O editor, as pré-visualizações e resolveStorageReferences os renovam quando
exibem o texto, porque um token ainda nomeia o seu objeto; reinserir a imagem
ou reescrever o texto com storageReferencesForDownloadUrls(text) armazena uma
referência.
Para onde o arquivo pode ir
Seção intitulada “Para onde o arquivo pode ir”storagePath é um padrão, não um limite restritivo: nada no servidor confina um
upload a esse prefixo. Decidir quem pode gravar onde é a finalidade de uma
regra de autorização de storage — consulte Storage.
Os arquivos nunca são excluídos por você
Seção intitulada “Os arquivos nunca são excluídos por você”Limpar um campo de arquivo, substituir seu arquivo, ou excluir a linha a que
ele pertence deixa o objeto armazenado onde está. Todo upload recebe sua
própria chave, então uma substituição grava um objeto novo em vez de
sobrescrever o antigo, e nada remove o anterior: duas linhas podem conter a
mesma chave, então o painel não tem como saber que um arquivo está sem uso.
Objetos aos quais nenhuma linha aponta permanecem no bucket, e são cobrados,
até que você os exclua — pelo navegador de storage do Studio, com
client.storage.deleteObject(key), ou com uma regra de ciclo de vida no
bucket. Desde 0.25 rebase storage orphans lista os arquivos que nenhuma linha nomeia e os exclui
com --delete — veja a CLI.
Movendo uma propriedade para outra fonte de storage
Seção intitulada “Movendo uma propriedade para outra fonte de storage”Um campo de arquivo armazena a chave do objeto, não sua fonte. Alterar o
storageSource de uma propriedade faz todo valor existente apontar para a
nova fonte, onde essas chaves não existem, então pré-visualizações de arquivos
enviados antes da mudança respondem “não encontrado”. Copie os objetos para a
nova fonte sob as mesmas chaves antes de alterar a propriedade — rebase storage move --from <old> --to <new> --prefix <storagePath>, ou com as próprias ferramentas do provedor, como aws s3 sync ou
gcloud storage cp — ou mantenha a fonte antiga para os arquivos existentes.
Próximos passos
Seção intitulada “Próximos passos”- Propriedades — todos os tipos de propriedade e suas opções
- Storage — buckets, URLs assinadas e o que o servidor faz com um upload
- Regras de Segurança (RLS) — quem pode ler as linhas às quais esses arquivos estão vinculados