File upload
File upload is an official field extension that requires a host service. Renderer handles selection, drag and drop, preflight validation, the concurrent queue, progress, cancellation, retry after failure, the uploaded-file list, and removal state. The host handles authorization, network transfer, storage, scanning, download, and deletion.
Controlled values contain only closed JSON file references. Browser File objects, Blobs, temporary URLs, upload credentials, request state, and progress never enter the FormDocument, FormPlan, or form value.
{
"attachments": [
{
"id": "release-notes",
"name": "release-notes.pdf",
"size": 184320,
"mediaType": "application/pdf"
}
]
}The example uses a local mock service to demonstrate progress and removal delay. It does not send or store file contents. Select a PDF or image to see the upload result appear immediately in the controlled value.
Value shape
Each file has four stable properties:
Reference objects reject additional properties. The host should resolve download URLs, signing parameters, access tokens, bucket names, and internal paths from id.
Schema
createFormFileUploadSchema creates a closed array-of-objects Schema with minimum and maximum file counts.
required means the array property must exist; minFiles specifies how many files that array must contain. These constraints serve different purposes.
UI node properties
Designer's properties panel edits accepted file types, the per-file limit, and concurrency. Its validation panel edits minimum and maximum file counts. The design canvas shows a summary of accepted types, size, and count without performing a real upload.
Host file service
createFileUploadNodeRegistry accepts a typed host service. Core and Renderer do not call a storage SDK directly.
All three requests include the same field context:
upload additionally receives the browser file and onProgress({ loaded, total? }). remove and optional open receive an already validated FormFileReference.
Service failures show a generic message without internal exceptions by default. To expose host error codes, map them to public copy with getErrorMessage:
Mapped messages display at most 500 characters. Do not return raw exceptions, response bodies, or credentials directly to the interface.
React
Custom component capabilities must enter both the compiler and Renderer. Designer adds component capabilities automatically from nodeRegistry; pass registration keys explicitly when compiling separately.
Vue
The Vue adapter forwards the same registry and controlled value, so it does not need another upload implementation.
Web Component
Pass the registry as an element property. Value changes continue to use the value-change event.
Interaction states
File type, size, and capacity are checked before any network request. At most 120 local tasks are retained at once to prevent abnormal selections from creating unbounded runtime state. Unmounting the component aborts any upload, removal, or open requests still in progress.
Keyboard and assistive technology
- File selection uses native
input[type="file"], which can receive focus with Tab and opens the system file picker through the browser. - Cancel, retry, open, and remove actions use button names containing the complete filename.
- Upload progress uses native
progresssemantics. - Successful uploads and removals are announced through
aria-live="polite". - Errors use
role="alert"; Schema errors continue to appear in the form error summary. - Long filenames are truncated visually, while the full name remains in the title and accessible name.
- In a 390px-wide container, the select button and file actions become a reachable vertical layout.
prefers-reduced-motiondisables nonessential transitions.
Security boundary
- Authorization checks must occur in the host service, not rely solely on the file picker's
acceptvalue. - MIME type, extension, and file content must be revalidated by a trusted service.
- Virus scanning, content moderation, quotas, retention policy, and audit are the host's responsibility.
- An
idshould be unguessable or resolved with authorization. openshould acquire short-lived access on demand instead of writing a signed URL to the form value.- After a successful upload, only the four declared properties are accepted; a return value with extra fields enters the failed state.
- Cancellation signals must reach the actual network request so an unmounted interface does not continue consuming bandwidth.
- Do not remove a reference from the controlled value before deletion succeeds, which would let interface state diverge from storage state.
