ngx-uploadx
July 15, 2026 · View on GitHub
Angular Resumable Upload Module
✨ Key Features
- Pause / Resume / Cancel uploads
- Automatic retries with exponential backoff
- Chunked uploads with adaptive chunk size
- Real-time progress, speed & ETA tracking
- Custom headers, metadata, authorization
- Drag & drop support via
uploadxDropdirective
⚡ Quick Start
- Add ngx-uploadx module as dependency:
npm install ngx-uploadx
- Add
uploadxdirective to the component template and provide the required options:
// Standalone component code
//...
import { UploadxDirective, UploadxOptions, UploadState } from 'ngx-uploadx';
@Component({
selector: 'upload-component',
template: ` <input type="file" [uploadx]="options" (state)="onUpload($event)" /> `,
imports: [UploadxDirective]
})
export class UploadComponent {
options: UploadxOptions = { endpoint: 'http://localhost:3000/upload' };
onUpload(state: UploadState) {
console.log(state);
//...
}
}
Please navigate to the src/app sub-folder for more detailed examples.
🖥️ Server-side setup
npm install @uploadx/core express
import { uploadx } from '@uploadx/core';
import express from 'express';
const app = express();
app.use(
'/upload',
uploadx({
uploadDir: './uploads',
maxFileSize: '20GB',
onComplete: file => {
console.log('File upload complete: ', file);
return file;
}
})
);
app.listen(3002);
📘 API Reference
Contents:
- UploadxOptions
- provideUploadx
- UploadxModule
- Directives
- UploadxService
- UploadState
- UploadxControlEvent
- DI tokens
UploadxOptions
-
allowedTypesAllowed file types (directive only) -
authorizeReplaces the default Bearer authorization logic(example) -
autoUploadAuto start upload when files added. Default value:true -
storeIncompleteHoursLimit upload lifetime. Default value:24 -
chunkSizeFixed chunk size. If not specified, the optimal size will be automatically adjusted based on the network speed. If set to0, normal uploading will be used instead of chunked -
maxChunkSizeDynamic chunk size limit -
concurrencySet the maximum parallel uploads. Default value:2 -
endpointURL to create new uploads. Default value:'/upload' -
responseTypeExpected server response type -
headersHeaders to be appended to each HTTP request -
metadataCustom metadata to be added to the uploaded files -
multipleAllow selecting multiple files. Default value:true(directive only) -
prerequestFunction called before every request (example) -
retryConfigObject to configure retry settings:maxAttemptsMaximum number of retry attempts. Default value:8shouldRestartCodesUpload not exist and will be restarted. Default value:[404, 410]authErrorCodesIf one of these codes is received, the request will be repeated with an updated authorization token. Default value:[401]shouldRetryCodesRetryable 4xx status codes. Default value:[408, 423, 429, 460]shouldRetryOverrides the built-in function that determines whether the operation should be retriedminDelayMinimum (initial) retry interval. Default value:500maxDelayMaximum retry interval. Default value:50_000onBusyDelayDelay used between retries for non-error responses with missing range/offset. Default value:1000timeoutTime interval after which unfinished requests must be retriedkeepPartialDetermines whether partial chunks should be kept
-
tokenAuthorization token as astringor function returning astringorPromise<string> -
uploaderClassUpload API implementation. Built-in:UploaderX(default),Tus. More examples
provideUploadx
Provides configuration options for standalone app (example).
bootstrapApplication(AppComponent, {
providers: [
provideUploadx({
endpoint: 'http://example.com/upload',
allowedTypes: 'video/*,audio/*',
maxChunkSize: 96 * 1024 * 1024
})
]
});
UploadxModule
Adds directives and provide static method withConfig for global configuration
@NgModule({
declarations: [AppComponent, UploadComponent],
imports: [
AppRoutingModule,
BrowserModule,
UploadxModule.withConfig({
allowedTypes: 'image/*,video/*',
endpoint: `${serverUrl}/files?uploadType=uploadx`,
headers: { 'ngsw-bypass': 'true' },
retryConfig: { maxAttempts: 5 }
})
],
providers: [],
bootstrap: [AppComponent],
exports: []
})
:bulb: No need to import
UploadxModuleif you do not use theuploadxoruploadxDropdirectives in your application.
Directives
<div uploadxDrop>
<label class="file-drop">
<input type="file" [uploadx]="options" [control]="control" (state)="onState($event)" />
</label>
</div>
uploadx
File input directive.
selectors: [uploadx], uploadx
Properties:
-
@Input() uploadx: UploadxOptionsSet directive options -
@Input() options: UploadxOptionsAlias foruploadxproperty -
@Input() control: UploadxControlEventControl the uploads -
@Output() state: EventEmitter<UploadState>Event emitted on upload state change
uploadxDrop
File drop directive.
selector: uploadxDrop
:bulb: Activates the
.uploadx-drop-activeclass on DnD operations.
UploadxService
Programmatic API for upload management. Use it when you need direct control over uploads from component code, dynamic configuration, or deep integration with application state.
-
init(options?: UploadxOptions): Observable<UploadState>Initializes service. Returns Observable that emits a new value on progress or status changes.
// @example: uploadxOptions: UploadxOptions = { concurrency: 4, endpoint: `${environment.api}/upload`, uploaderClass: Tus }; ngOnInit() { this.uploadService.init(this.uploadxOptions) .subscribe((state: UploadState) => { console.log(state); // ... } } -
connect(options?: UploadxOptions): Observable<Uploader[]>Initializes service. Returns Observable that emits the current queue.
// @example: @Component({ template: ` <input type="file" uploadx"> <div *ngFor="let item of uploads$ | async">{{item.name}}</div> `, changeDetection: ChangeDetectionStrategy.OnPush }) export class UploadsComponent { uploads$: Observable<Uploader[]>; options: UploadxOptions = { endpoint: `${environment.api}/upload?uploadType=uploadx`, headers: { 'ngsw-bypass': 1 } } constructor(private uploadService: UploadxService) { this.uploads$ = this.uploadService.connect(this.options); } -
disconnect(): voidTerminate all uploads and clears the queue.
-
ngOnDestroy(): voidCalled when the service instance is destroyed. Interrupts all uploads and clears the queue and subscriptions.
:bulb: Normally
ngOnDestroy()is never called becauseUploadxServiceis an application-wide service, and uploading will continue even after the upload component is destroyed. -
handleFiles(files: FileList | File | File[], options = {} as UploadxOptions): void// @example: onFilesSelected(): void { this.uploadService.handleFiles(this.fileInput.nativeElement.files); }Creates uploaders for files and adds them to the upload queue.
-
control(event: UploadxControlEvent): voidUploads control. Available actions:
upload,cancel,pause,update.// @example: pause(uploadId?: string) { this.uploadService.control({ action: 'pause', uploadId }); } setToken(token: string) { this.uploadService.control({ token }); } -
request<T = string>(config: AjaxRequestConfig): Promise<AjaxResponse<T>>Make HTTP request with
axioslike interface.// @example: import { AjaxRequestConfig, UploadxService } from 'ngx-uploadx'; class MyService { constructor(private uploadService: UploadxService) {} async fetchUploads() { const config: AjaxRequestConfig = { url: '/api/uploads', method: 'GET' }; const response = await this.uploadService.request(config); return response.items; } } -
state(): UploadState[]Returns the current state of uploads.
// @example: uploads: UploadState[]; constructor(private uploadService: UploadxService) { // restore background uploads this.uploads = this.uploadService.state(); } -
queue: Uploader[]Uploaders array.
// @example: export class UploadComponent { state: UploadState; options: UploadxOptions = { concurrency: 1, multiple: false, endpoint: `${environment.api}/upload`, } constructor(private uploadService: UploadxService) { this.state = this.uploadService.queue[0] || {}; } -
events: Observable<UploadState>Uploads state events.
UploadState
Upload state object emitted by the service:
interface UploadState {
readonly file: File; // Uploaded file
readonly name: string; // Original file name
readonly progress: number; // Progress percentage
readonly remaining: number; // Estimated remaining time
readonly response: ResponseBody; // HTTP response body
readonly responseStatus: number; // HTTP response status code
readonly responseHeaders: Record<string, string>; // HTTP response headers
readonly size: number; // File size in bytes
readonly speed: number; // Upload speed bytes/sec
readonly status: UploadStatus; // Upload status
readonly uploadId: string; // Unique upload id
readonly url: string; // File url
}
type UploadStatus =
| 'added'
| 'queue'
| 'uploading'
| 'complete'
| 'error'
| 'cancelled'
| 'paused'
| 'retry'
| 'updated';
UploadxControlEvent
Control event type for uploadService.control():
interface UploadxControlEvent {
action?: 'upload' | 'cancel' | 'pause' | 'update';
uploadId?: string; // Target upload ID (optional - affects all if not provided)
endpoint?: string; // URL to create new uploads
headers?: RequestHeaders; // Headers to be appended
metadata?: Metadata; // Custom uploads metadata
token?: string; // Authorization token
}
DI tokens
-
UPLOADX_FACTORY_OPTIONS: override default configuration -
UPLOADX_OPTIONS: global options -
UPLOADX_AJAX: override internal ajax lib
🧪 Demo
Checkout the Demo App or run it on your local machine:
- Run script
npm start - Navigate to
http://localhost:4200/
🛠️ Build
Run npm run build:pkg to build the lib.
packaged by ng-packagr
🐞 Bugs and Feedback
For bugs, questions and discussions please use the GitHub Issues.
🤝 Contributing
Pull requests are welcome!
To contribute, please read contributing instructions.
📄 License
The MIT License (see the LICENSE file for the full text)