File Upload
Let users pick or drag files into your application, upload them to configured storage, and expose the resulting file URLs and metadata for use in downstream actions and data sources.
Overview
The File Upload block accepts files via drag-and-drop or click-to-browse, uploads them to your workspace's configured cloud storage, and exposes the results as file descriptors — not raw bytes. You control which file types are allowed, how many files can be attached at once, a per-file size cap, who can access the stored files, and whether users can download them. An optional template file link and description add-on round out the UI.
The equivalent inside a Form block is the File Uploader form field, which participates in form submit, validation, and reset flows. Use the standalone block for page-level upload controls outside a form context.
Note: What gets stored? The file bytes go to cloud storage. What your logic receives is a descriptor object with id, name, url, size, mimeType, fileType (extension), sourceType, and source. Always read the URL or ID off this object; the binary file itself is never available in no-code expressions.
Block vs. Form Field
| Aspect | Standalone Block | File Uploader Form Field |
| Where it lives | Anywhere on the page | Inside a Form block |
| Value access | {{ id.files }} (array) | {{ form.data.fieldKey }} (object or array) |
| Validation | Manual (bind to disabled state) | Is Optional, Validity Conditions, Max Files, Max Size |
| Reset | removeFiles method | Form resetForm clears it |
| Multiple files | Via selectionVariant = multiple | Via Allow multiple files toggle |
| Submit integration | No — read files manually | Yes — included in form payload |
File Restrictions
| Property | Type | Default | Description |
label | string | Upload File | Heading shown above the drop zone. Translatable. |
supportedFileTypes | string[] | Any File | Multi-select catalog of accepted types: Any File, Audio, CSV, Documents, Excel (2007+, 97-2003, Binary), Folder (folder-pick mode), ICO, Images, JPEG/JPG, JSON, Lottie, Markdown, PDF, PNG, PowerPoint, SVG, Text, Videos, Word Document, XML, XSD, ZIP, and Outlook .msg. Selecting JPG also accepts JPEG silently. |
selectionVariant | "single" | "multiple" | single | Whether the user can attach one or several files at once. |
maxFiles | number | — (no limit) | Maximum number of files. Appears only when selectionVariant is multiple. When reached, the entire drop zone disables itself. |
maxFileSize | number (MB) | — | Per-file size cap in megabytes. Applies to each file individually, not to the combined total. |
Warning: Folder type is special: Adding Folder to Supported File Types turns on folder-picking mode (the user selects a whole directory), not a file extension filter. It strips "Folder" from the accept list and instead switches the native file picker into folder mode.
Access & File Visibility
The File Visibility setting controls who can open a stored file after upload. The available options depend on the workspace's cloud storage provider.
| Option | Who can access | Notes |
| Public | Anyone — no sign-in required | Inline warning banner is shown. The control is shown only if the provider supports public access. |
| Restricted | All authenticated users | Default. Works on all providers. |
| Only Me (block) / Only this app (screen) | Uploader only / App users only | Not available on S3 without public-upload configured. If unsupported, the control disappears and files default to Restricted. |
The app-level default for file visibility is set under App Settings → Advanced Settings → File Management. Individual block instances can override it. The visibility control on the block and on the form field both follow this hierarchy.
Allow Download (boolean, default true) — shows a download control in the uploaded file list. Turning it off hides the download action for users, but does not affect the url in state.
Add-ons
| Add-on | What it does |
| Description | Helper text rendered below the drop zone, for instructions the label doesn't cover. |
| Template File | Adds a downloadable template link in the block header. Set a Label, an Icon, and either a URL or an uploaded file as the source. Useful for "download this format, fill it in, upload it back" flows. |
Appearance
| Property | Type | Default | Description |
uploadIcon | icon | SvgUploadCloud02 | Icon shown inside the empty drop zone. |
disabled | condition | — | Condition that greys out the block and blocks uploads when true. Also triggered automatically when maxFiles is reached. |
visibility | condition | — | Hides the block when the condition is false. |
styles | style set | — | Border (Stroke), Radius, and background Color for the drop zone. |
Exposed State
Key ({{ id.* }}) | Type | Description |
files | array | All currently attached files. Each item has: id, name, url, size, mimeType, fileType (extension), sourceType (CLOUD_STORAGE or URL), source, progress (0–100), and isUploaded (boolean). |
isUploading | boolean | true while any file in the block is still uploading. |
content.supportedFileTypes | array | The configured accepted file-type tokens. |
content.selectionVariant | string | "single" or "multiple". |
Warning: During upload, url is a local blob — not a real link. While isUploaded is false, url points to a temporary browser blob preview useful for thumbnails, but useless as a shareable or storable link. Only after upload completes does isUploaded flip to true and url become the real backend download URL. Always gate any "save" or "submit" action on {{ id.isUploading }} being false.
Events & Methods
Events
| Event | When it fires | Notes |
| On File Uploaded | Once, after every file in the current batch has finished uploading | Fires on the transition from "uploading" to "idle". Dropping five files at once fires the event once, not five times. For per-file reactions, watch the {{ id.files }} list. |
Methods
| Method | Parameters | Description |
| removeFile | fileId | Removes one file by its ID from the block's list. |
| removeFiles | — | Clears every file from the block at once. |
File Uploader Form Field
When you need file upload as part of a form submission flow, use the FILE_UPLOADER form field instead of the standalone block. It lives inside a Form block and participates in validation, reset, and the submit payload.
Key differences from the standalone block
Multiple vs. single mode: Controlled by Allow multiple files toggle. Single mode stores one file object; multiple mode stores an array.
Validation: Maximum Files, Maximum File Size (MB), and Supported File Types live in the Validation section. Is Optional controls whether at least one file is required.
Value shape: Single mode —
{{ form.data.key }}is one object{ id, name, url, sourceType, type }. Multiple mode — an array of such objects. Read.urlor.idto pass to downstream queries.Events: On Change (fires when a file finishes uploading or is removed), On Focus, On Blur.
Default value: Accepts an array of file objects for pre-filling the field. A dynamic default overwrites user-added files when the bound value changes.
File Uploader field properties
| Property | Type | Default | Description |
Allow multiple files | boolean | false | When on, multiple files allowed and value becomes an array. |
Allow download | boolean | true | Shows a download action on each uploaded file row. |
File visibility | PUBLIC | RESTRICTED | ONLY_ME | RESTRICTED | Who can access stored files. Only Me not shown on S3. |
Maximum files | number | — | Max count; uploader disables once reached. |
Maximum file size (MB) | number | — | Per-file size cap in megabytes. |
Supported file types | array | — | Same catalog as the block; empty or Any File accepts everything. |
Is optional | boolean | true | When off, at least one file must be attached before submit. |
Behavior & Gotchas
The value is file descriptors, not raw binary data
What you get from {{ id.files }} is a list of descriptor objects — id, name, size, mime type, and a URL. There is no File object or byte stream available in no-code logic. To persist an upload, save the url or the storage id from the descriptor.
On File Uploaded fires once per batch, not once per file
Drop five files at once and the event fires a single time after the last file finishes, not five times. If you need per-file reactions, watch the {{ id.files }} array or its length changing rather than relying on the event.
Uploaded files are cleared when the block unmounts
When the block unmounts — a modal closes, the user navigates away — the file list is wiped. Files do not survive being hidden-by-unmount and re-shown. Read the files out before the modal closes or the user navigates.
You cannot pre-fill the block with existing files
The block always starts empty on every load. There is no content property that seeds it with previously uploaded files. To show files a record already has, use a separate display element (Image, attachment list, etc.); the File Upload block is for capturing new uploads only.
After the first file, the drop zone stops being click-to-upload
The empty state is fully clickable. Once one file is present, the card itself is no longer clickable. In multiple mode, an "Upload more" button stays available. In single mode, the user must remove the existing file before adding another.
"Only Me" visibility depends on the storage provider
The Only Me option is not offered on S3-backed storage. On S3 without public-upload enabled, the entire File Visibility control may be hidden and uploads default to Restricted. Public visibility also only truly serves files anonymously on providers that support it.
A rejected file does not block others in the same batch
Files that fail type/size checks show an inline error instead of uploading. Other valid files in the same batch still upload normally — a rejection is per-file, not per-batch.
Frequently Asked Questions
How do I access the URL of an uploaded file to save it to a record?
For the standalone block, read {{ id.files[0].url }} for the first file's URL after upload completes (check {{ id.isUploading }} is false first). For the form field in single mode, read {{ form.data.fieldKey.url }}. In multiple mode, loop over the array to collect each url. Note that during upload, url is a temporary browser blob — wait for isUploaded: true before saving.
Why does the On File Uploaded event only fire once even when I drop multiple files?
This is by design. The event fires once per batch — after all files in the current drop finish uploading, not once per individual file. If you need per-file reactions, watch {{ id.files }} array changes, or check each file's isUploaded flag reactively.
Can I restrict uploads to PDF and Word only, and prevent other types?
Yes. In File Restrictions → Supported File Types, select PDF and Word Document. Files of any other type will be rejected before upload with an inline error; valid files in the same drop still upload normally. The browser file picker will also be filtered to show only those types.
Why does my File Upload block reset when the containing modal closes?
When the block unmounts (a modal closing is a common trigger), the file list is automatically cleared. This is expected — the block stores files in transient memory, not persistent state. Always read {{ id.files }} (or submit the form) before closing the modal. Wire your "Save" action to run before the modal close action.
The file uploader form field shows an empty array in my data — why?
Removing the last file from the field stores an empty value (not an array), so "is this field filled" checks behave consistently in both single and multiple modes. Also confirm that your validation condition isn't treating an empty value as an array — when empty, the field holds undefined, not [].