Pular para o conteúdo

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.

avatar: {
type: "string",
name: "Main image",
storage: {
storagePath: "avatars",
acceptedFiles: ["image/*"],
maxSize: 2 * 1024 * 1024
}
}

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/*"] }
}
}

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.

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.

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, como putObject({ 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 storagePath escrito 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).

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 — ![](rebase-storage:posts/abc_cover.png) — 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.

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.

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.

  • 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