Campi di caricamento file
Un campo file è una normale proprietà string con un blocco storage. La
colonna contiene testo — la chiave dell’oggetto nel bucket o il suo URL se
richiesto — e il blocco specifica dove vanno i byte e cosa accetterà il form.
Questa separazione conta più di quanto sembri. La maggior parte di storage viene
letta dall’uploader del pannello di amministrazione durante l’invio all’API, quindi
una scrittura che non proviene da un form non passa attraverso di esso — tali opzioni
presentano l’etichetta di seguito. Le due che decidono cosa un file possa essere,
maxSize e acceptedFiles, fanno eccezione: il server le controlla a ogni caricamento nello storagePath della proprietà.
Un singolo file
Sezione intitolata “Un singolo file”avatar: { type: "string", name: "Main image", storage: { storagePath: "avatars", acceptedFiles: ["image/*"], maxSize: 2 * 1024 * 1024 }}File multipli
Sezione intitolata “File multipli”Un array della stessa cosa. Il blocco storage si sposta in of, poiché
descrive ciascun elemento anziché l’elenco:
images: { type: "array", name: "Images", of: { type: "string", storage: { storagePath: "images", acceptedFiles: ["image/*"] } }}Opzioni di storage
Sezione intitolata “Opzioni di storage”Tutto ciò che si trova all’interno di storage.
| Proprietà | Tipo | Descrizione |
|---|---|---|
storagePath |
string | function |
Obbligatorio. Dove va a finire il file nel bucket. Una stringa con segnaposto — {file}, {file.name}, {file.ext}, {rand}, {entityId}, {propertyKey}, {path} — o una funzione del contesto di caricamento. Solo form di amministrazione — non applicato dall’API o dal database: è l’uploader del pannello che lo risolve, e client.storage.upload() definisce la propria chiave. Un percorso a stringa è anche dove il server verifica ogni caricamento rispetto a maxSize e acceptedFiles di questa proprietà |
fileName |
string | function |
Il nome file dell’oggetto caricato, con gli stessi segnaposto. Solo form di amministrazione — non applicato dall’API o dal database. |
storageSource |
string |
Quale bucket registrato utilizzare, quando un progetto ne ha più di uno. Anche l’handle bucket("media") funziona qui |
public |
boolean |
Memorizza sotto il prefisso pubblico e distribuisce tramite un URL stabile, senza token e memorizzabile nella cache. false per impostazione predefinita, il che implica oggetti privati e URL firmati a breve durata |
acceptedFiles |
FileType[] |
Tipi MIME accettati da questa proprietà. È supportata la forma con asterisco — image/*. Applicato dal server per ogni caricamento nello storagePath della proprietà — vedi Cosa controlla il server |
maxSize |
number |
Dimensione massima accettata del file, in byte. Applicato dal server, come acceptedFiles, sia per i percorsi di caricamento standard sia per quelli riprendibili |
metadata |
Record<string, unknown> |
Metadati dell’oggetto da archiviare insieme al file |
includeBucketUrl |
boolean |
Scrive s3://my-bucket/path/to/file.png nella colonna anziché path/to/file.png. false per impostazione predefinita |
storeUrl |
boolean |
Scrive l’URL di download nella colonna anziché la chiave. false per impostazione predefinita, ed è consigliabile lasciarlo così: un URL che include un token smette di funzionare alla scadenza del token, e il riferimento originale va perso |
imageResize |
ImageResize |
Ridimensiona e ritaglia prima del caricamento, per image/jpeg, image/png e image/webp. Solo form di amministrazione — non applicato dall’API o dal database. |
processFile |
(file: File) => Promise<File> |
Trasforma il file prima che venga caricato. Viene eseguito nel browser. Solo form di amministrazione — non applicato dall’API o dal database. |
postProcess |
(pathOrUrl: string) => Promise<string> |
Trasforma il percorso o l’URL risolto prima che venga salvato. Viene eseguito nel browser. Solo form di amministrazione — non applicato dall’API o dal database. |
previewUrl |
(fileName: string) => string |
Costruisce l’URL di anteprima, per quando l’indirizzo reale del file non coincide con il valore del campo. Solo form di amministrazione — non applicato dall’API o dal database. |
Ridimensionamento
Sezione intitolata “Ridimensionamento”imageResize accetta maxWidth e maxHeight in pixel, una mode impostata su
"contain" (ridimensiona per adattare, valore predefinito) o "cover" (riempie i limiti e
ritaglia), un format tra "original", "jpeg", "png" o "webp" e una
quality compresa tra 0 e 100 per i formati con perdita — 80 per impostazione predefinita. Avviene
nel browser prima che i byte vengano inviati, quindi un caricamento che non proviene dal
pannello viene archiviato con le sue dimensioni originali.
Cosa controlla il server
Sezione intitolata “Cosa controlla il server”In passato, maxSize e acceptedFiles venivano applicati da un’unica cosa: il
browser. La route di caricamento conosceva solo un limite di dimensione globale e nulla riguardo
alla proprietà a cui un file era destinato; quindi curl -F file=@payload.exe oltrepassava il selettore
inserendo un eseguibile da 40 MB nel bucket degli avatar, senza che la configurazione contraria
venisse mai consultata.
Entrambi vengono ora verificati dal server in base a dove finisce il file.
Sulla 0.23 venivano verificati solo rispetto alla proprietà indicata da un
caricamento, e un caricamento che non ne nomina alcuna incontra solo il limite
proprio della sorgente. Lo
storagePath di una proprietà è dove vanno i suoi file, quindi è anche dove
valgono i suoi limiti: ogni caricamento la cui chiave è un file direttamente
sotto quel percorso — dal pannello, da client.storage.putObject, da un
caricamento riprendibile, dal browser di storage di Studio o da curl — li
rispetta, che nomini o no la proprietà, sulla sorgente di storage propria della
proprietà. I segnaposto corrispondono a ciò che il pannello inserirebbe:
{entityId}, {rand}, {file} e simili rappresentano un singolo segmento di
percorso, {path} un numero qualsiasi di segmenti. Il percorso di una
proprietà public: true è sotto public/.
- Più proprietà che condividono un percorso: un file accettato da una di esse viene accettato.
- Un caricamento che indica anche la propria proprietà (
collection+property, come li inviaputObject({ context })) è vincolato anche a quella proprietà. Indicare una proprietà più permissiva non sblocca il percorso di una più restrittiva. I caricamenti del pannello (campi file, celle di tabella e immagini markdown) la indicano sempre. - Uno
storagePathscritto come funzione non può essere letto senza eseguirlo, quindi non ha una regola lato server: quei limiti valgono solo per i caricamenti che indicano la proprietà, cosa che fanno quelli del pannello. - Un percorso che nessuna proprietà dichiara è vincolato solo al limite
proprio della sorgente (
STORAGE_MAX_FILE_SIZE).
Immagini in un campo markdown
Sezione intitolata “Immagini in un campo markdown”Una proprietà markdown (admin.markdown: true) con un blocco storage
accetta caricamenti di immagini nel suo editor. Il testo memorizza ogni
immagine come riferimento di storage — 
— non come URL: l’URL di un file privato porta un token di download che scade
in pochi minuti, mentre il testo viene salvato. L’editor e le anteprime del
pannello di amministrazione scambiano ogni riferimento con un URL nuovo quando
lo mostrano; un sito che esegue il rendering del campo fa lo stesso con
resolveStorageReferences(text, client) — vedi
File dentro un testo.
Un testo salvato prima dei riferimenti contiene gli URL di download stessi, con
token scaduti. L’editor, le anteprime e resolveStorageReferences li rinnovano quando
mostrano il testo, perché un token nomina ancora il suo oggetto; reinserire l’immagine
o riscrivere il testo con storageReferencesForDownloadUrls(text) memorizza un
riferimento.
Dove è consentito collocare il file
Sezione intitolata “Dove è consentito collocare il file”storagePath è un valore predefinito, non un vincolo invalicabile: nulla sul server limita un
caricamento a quel prefisso. Decidere chi può scrivere dove è lo scopo di una regola di
autorizzazione dello storage — consultare Storage.
I file non vengono mai eliminati per te
Sezione intitolata “I file non vengono mai eliminati per te”Svuotare un campo file, sostituire il suo file, o eliminare la riga a cui
appartiene lascia l’oggetto memorizzato dov’è. Ogni caricamento ottiene una
propria chiave, quindi una sostituzione scrive un nuovo oggetto invece di
sovrascrivere quello vecchio, e nulla rimuove il precedente: due righe possono
condividere la stessa chiave, quindi il pannello non può sapere che un file
non è più usato. Gli oggetti a cui nessuna riga punta restano nel bucket, e
vengono fatturati, finché non li elimini — dal browser di storage di Studio,
con client.storage.deleteObject(key), o con una regola di lifecycle sul
bucket. Da 0.25 rebase storage orphans elenca i file che nessuna riga nomina, e li elimina
con --delete — vedi la CLI.
Spostare una proprietà su un’altra sorgente di storage
Sezione intitolata “Spostare una proprietà su un’altra sorgente di storage”Un campo file memorizza la chiave dell’oggetto, non la sua sorgente. Cambiare
lo storageSource di una proprietà fa puntare ogni valore esistente alla
nuova sorgente, dove quelle chiavi non esistono, quindi le anteprime dei file
caricati prima della modifica rispondono “non trovato”. Copia gli oggetti
sulla nuova sorgente con le stesse chiavi prima di modificare la proprietà —
rebase storage move --from <old> --to <new> --prefix <storagePath>, o con gli strumenti propri del provider, come aws s3 sync o
gcloud storage cp — oppure conserva la vecchia sorgente per i file
esistenti.
Prossimi passi
Sezione intitolata “Prossimi passi”- Properties — ciascun tipo di proprietà e le relative opzioni
- Storage — bucket, URL firmati e cosa fa il server con un caricamento
- Security Rules (RLS) — chi può leggere le righe a cui sono associati questi file