/** * @license * Copyright (c) 2000 - 2026 Vaadin Ltd. * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ */ export type UploadMethod = 'POST' | 'PUT'; export type UploadFormat = 'raw' | 'multipart'; export type FileRejectError = 'tooManyFiles' | 'fileIsTooBig' | 'incorrectFileType'; export type UploadErrorKey = | 'timeout' | 'serverUnavailable' | 'unexpectedServerError' | 'forbidden' | 'sendFailed' | 'fileTooLarge'; export interface UploadFile extends File { uploadTarget: string; elapsed: number; remaining: number; progress: number; speed: number; total: number; loaded: number; status: string; errorKey: UploadErrorKey; abort?: boolean; complete?: boolean; held?: boolean; uploading?: boolean; indeterminate?: boolean; stalled?: boolean; formDataName?: string; xhr?: XMLHttpRequest; } export interface UploadManagerOptions { /** * The server URL. The default value is an empty string, which means that * _window.location_ will be used. * @default '' */ target?: string; /** * HTTP Method used to send the files. Only POST and PUT are allowed. * @default 'POST' */ method?: UploadMethod; /** * Key-Value map to send to the server. If you set this property as an * attribute, use a valid JSON string, for example: * ```html * * ``` * @default {} */ headers?: Record; /** * Max time in milliseconds for the entire upload process, if exceeded the * request will be aborted. Zero means that there is no timeout. * @default 0 */ timeout?: number; /** * Limit of files to upload, by default it is unlimited. If the value is * set to one, native file browser will prevent selecting multiple files. * @default Infinity */ maxFiles?: number; /** * Specifies the maximum file size in bytes allowed to upload. * Notice that it is a client-side constraint, which will be checked before * sending the request. Obviously you need to do the same validation in * the server-side and be sure that they are aligned. * @default Infinity */ maxFileSize?: number; /** * Specifies the types of files that the server accepts. * Syntax: a comma-separated list of MIME type patterns (wildcards are * allowed) or file extensions. * Notice that MIME types are widely supported, while file extensions * are only implemented in certain browsers, so avoid using it. * Example: accept="video/*,image/tiff" or accept=".pdf,audio/mp3" * @default '' */ accept?: string; /** * Prevents upload(s) from immediately uploading upon adding file(s). * When set, you must manually trigger uploads using the `uploadFiles` method. * @default false */ noAuto?: boolean; /** * Set the withCredentials flag on the request. * @default false */ withCredentials?: boolean; /** * Specifies the upload format to use when sending files to the server. * - 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default) * - 'multipart': Send file using multipart/form-data encoding * @default 'raw' */ uploadFormat?: UploadFormat; /** * Specifies the maximum number of files that can be uploaded simultaneously. * This helps prevent browser performance degradation and XHR limitations when * uploading large numbers of files. Files exceeding this limit will be queued * and uploaded as active uploads complete. * @default 3 */ maxConcurrentUploads?: number; /** * Specifies the 'name' property at Content-Disposition for multipart uploads. * This property is ignored when uploadFormat is 'raw'. * @default 'file' */ formDataName?: string; /** * Whether the upload manager is disabled. * When true, connected components (upload-button, upload-drop-zone) will be automatically disabled. * @default false */ disabled?: boolean; } export interface UploadManagerEventMap { 'file-reject': CustomEvent<{ file: File; error: FileRejectError }>; 'file-remove': CustomEvent<{ file: UploadFile; fileIndex: number }>; 'upload-before': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-request': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest; uploadFormat: UploadFormat; requestBody: UploadFile | FormData; formData?: FormData; }>; 'upload-start': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-progress': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-response': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-success': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-error': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-retry': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'upload-abort': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>; 'files-changed': CustomEvent<{ value: UploadFile[] }>; 'max-files-reached-changed': CustomEvent<{ value: boolean }>; 'disabled-changed': CustomEvent<{ value: boolean }>; } /** * A pure JavaScript class that manages file upload state and XHR requests. * It has no knowledge of UI components - components should listen to events * and call methods to interact with the manager. * * @example * ```javascript * import { UploadManager } from '@vaadin/upload'; * * const manager = new UploadManager({ * target: '/api/upload', * maxFiles: 5 * }); * * // Listen to state changes * manager.addEventListener('files-changed', (e) => { * myFileList.items = e.detail.value; * }); * * manager.addEventListener('upload-success', (e) => { * console.log('File uploaded:', e.detail.file.name); * }); * * // Add files (e.g., from a file input or drop event) * fileInput.addEventListener('change', (e) => { * manager.addFiles(e.target.files); * }); * ``` */ export class UploadManager extends EventTarget { /** * Create an UploadManager instance. */ constructor(options?: UploadManagerOptions); /** * The server URL. The default value is an empty string, which means that * _window.location_ will be used. */ target: string; /** * HTTP Method used to send the files. Only POST and PUT are allowed. */ method: UploadMethod; /** * Key-Value map to send to the server. If you set this property as an * attribute, use a valid JSON string, for example: * ```html * * ``` */ headers: Record; /** * Max time in milliseconds for the entire upload process, if exceeded the * request will be aborted. Zero means that there is no timeout. */ timeout: number; /** * Limit of files to upload, by default it is unlimited. If the value is * set to one, native file browser will prevent selecting multiple files. */ maxFiles: number; /** * Specifies the maximum file size in bytes allowed to upload. * Notice that it is a client-side constraint, which will be checked before * sending the request. Obviously you need to do the same validation in * the server-side and be sure that they are aligned. */ maxFileSize: number; /** * Specifies the types of files that the server accepts. * Syntax: a comma-separated list of MIME type patterns (wildcards are * allowed) or file extensions. * Notice that MIME types are widely supported, while file extensions * are only implemented in certain browsers, so avoid using it. * Example: accept="video/*,image/tiff" or accept=".pdf,audio/mp3" */ accept: string; /** * Prevents upload(s) from immediately uploading upon adding file(s). * When set, you must manually trigger uploads using the `uploadFiles` method. */ noAuto: boolean; /** * Set the withCredentials flag on the request. */ withCredentials: boolean; /** * Specifies the upload format to use when sending files to the server. * - 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default) * - 'multipart': Send file using multipart/form-data encoding */ uploadFormat: UploadFormat; /** * Specifies the maximum number of files that can be uploaded simultaneously. * This helps prevent browser performance degradation and XHR limitations when * uploading large numbers of files. Files exceeding this limit will be queued * and uploaded as active uploads complete. */ maxConcurrentUploads: number; /** * Specifies the 'name' property at Content-Disposition for multipart uploads. * This property is ignored when uploadFormat is 'raw'. */ formDataName: string; /** * The array of files being processed, or already uploaded. * * Each element is a [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) * object with a number of extra properties to track the upload process: * - `uploadTarget`: The target URL used to upload this file. * - `elapsed`: Elapsed time since the upload started. * - `remaining`: Number of seconds remaining for the upload to finish. * - `progress`: Percentage of the file already uploaded. * - `speed`: Upload speed in kB/s. * - `size`: File size in bytes. * - `total`: The total size of the data being transmitted or processed * - `loaded`: Bytes transferred so far. * - `status`: Status of the upload process. * - `errorKey`: Error key in case the upload failed. * - `abort`: True if the file was canceled by the user. * - `complete`: True when the file was transferred to the server. * - `uploading`: True while transferring data to the server. */ files: UploadFile[]; /** * Specifies if the maximum number of files have been uploaded. */ readonly maxFilesReached: boolean; /** * Whether the upload manager is disabled. * When true, connected components (upload-button, upload-drop-zone) will be automatically disabled. */ disabled: boolean; /** * Add files to the upload list. */ addFiles(files: FileList | File[]): void; /** * Triggers the upload of any files that are not completed. * * @param files Files being uploaded. Defaults to all outstanding files. */ uploadFiles(files?: UploadFile | UploadFile[]): void; /** * Retry a failed upload. */ retryUpload(file: UploadFile): void; /** * Abort an upload. */ abortUpload(file: UploadFile): void; /** * Remove a file from the list. */ removeFile(file: UploadFile): void; addEventListener( type: K, listener: (this: UploadManager, ev: UploadManagerEventMap[K]) => void, options?: boolean | AddEventListenerOptions, ): void; addEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions, ): void; removeEventListener( type: K, listener: (this: UploadManager, ev: UploadManagerEventMap[K]) => void, options?: boolean | EventListenerOptions, ): void; removeEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions, ): void; }