Awesome
ngxf-uploader
File uploader for Angular 6+, just use Angular HttpClient, no other dependence. GitHub
- ✅
file
upload - ✅
multiple File
upload - ✅
accept
support - ✅
Progress
support - ✅
upload http request
support - ✅
folder
upload, thanks for SHANG-TING, more detail about file upload with folder, can view his blog
Stackblitz Example
Future
[
{
"name": "folder name",
"files": [...files],
}
]
Description
Select file or Drop, Paste file, and return an Observable. You can custom your behavior use RxJs 7.x .
Provide an sample way for upload by custom options like header, params, fields, file's form name.
Example
Install
npm install ngxf-uploader --save
- Import
HttpClientModule
,NgxfUploaderModule
into your main AppModule or the module where you want use.
import { provideHttpClient } from '@angular/common/http';
import { provideExperimentalZonelessChangeDetection, model, inject } from '@angular/core';
import { of, catchError, finalize, tap } from 'rxjs';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { FileError, NgxfDirectoryStructure, NgxfDropDirective, NgxfSelectDirective, NgxfUploaderService, UploadEvent, UploadStatus, NgxfParseDirective } from 'ngxf-uploader';
@Component({
selector: 'app-root',
standalone: true,
imports: [NgxfSelectDirective, NgxfDropDirective, NgxfParseDirective],
templateUrl: './app.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class App {
progress = 0;
isUploading = false;
upload = inject(NgxfUploaderService);
uploadFile(file: File | File[] | NgxfDirectoryStructure[] | FileError) {
console.log(file);
this.isUploading = true;
if (!(file instanceof File) || Array.isArray(file)) {
// this.alertError(file);
this.isUploading = false;
return;
}
this.upload
.upload({
url: 'your api url',
headers: {
Authorization: 'token',
}, // Option
params: {
test: '123',
}, // Option
fields: {
// Option
toUrl: 'device',
},
filesKey: 'fileKey', // Option
files: file,
process: true,
})
.pipe(
tap((event: UploadEvent) => {
console.log(event);
this.progress = event.percent || 0;
if (event.status === UploadStatus.Completed) {
alert(`This file upload success!`);
}
}),
catchError((err) => {
console.error(err);
// alert(`upload fail`);
return of(null);
}),
finalize(() => {
console.log('end');
}),
)
.subscribe();
}
// Do something you want when file error occur.
alertError(msg: FileError) {
switch (msg) {
case FileError.NumError:
alert('Number Error');
break;
case FileError.SizeError:
alert('Size Error');
break;
case FileError.TypeError:
alert('Type Error');
break;
}
}
}
bootstrapApplication(App, {
providers: [provideHttpClient(), provideExperimentalZonelessChangeDetection()],
});
- Add directive in the template where you want to use.
<!-- select file -->
<button (ngxf-select)="uploadFile($event)">Upload Single File</button>
<!-- drop file & parse image -->
<div (ngxf-drop)="uploadFiles($event)" (ngxf-parse)="uploadFiles($event)" [ngxf-validate]="{size: {min: 5000, max:2566621}, skipInvalid: true}" drop-class="drop" accept="image/*" multiple>
<h3>Drop file and parse image into here or click here to choice file.</h3>
</div>
- Add
NgxfUploaderService
in the constructor and create file upload method in the typescript and upload file to server.
import { Component } from '@angular/core';
import { FileError, NgxfUploaderService, UploadEvent, UploadStatus } from 'ngxf-uploader';
@Component({
selector: 'app-drop-file',
templateUrl: './drop-file.component.html',
styleUrls: ['./drop-file.component.scss'],
})
export class DropFileComponent {
progress = 0;
isUploading = false;
constructor(private Upload: NgxfUploaderService) {}
uploadFile(file: File | FileError): void {
console.log(file);
this.isUploading = true;
if (!(file instanceof File)) {
this.alertError(file);
this.isUploading = false;
return;
}
this.Upload.upload({
url: 'your api url',
headers: {
Authorization: 'token',
}, // Option
params: {
test: '123',
}, // Option
fields: {
// Option
toUrl: 'device',
},
filesKey: 'fileKey', // Option
files: file,
process: true,
}).subscribe(
(event: UploadEvent) => {
console.log(event);
this.progress = event.percent;
if (event.status === UploadStatus.Completed) {
alert(`This file upload success!`);
}
},
(err) => {
console.log(err);
},
() => {
this.isUploading = false;
console.log('complete');
},
);
}
uploadFiles(files: File[] | FileError): void {
console.log(files);
this.isUploading = true;
if (!(files instanceof Array)) {
this.alertError(files);
this.isUploading = false;
return;
}
this.Upload.upload({
url: 'your api url',
headers: {
Authorization: 'token',
}, // Option
params: {
test: '123',
}, // Option
fields: {
// Option
toUrl: 'device',
},
filesKey: 'fileKey', // Option
files: files,
process: true, // if you want process event, set process true
}).subscribe(
(event: UploadEvent) => {
console.log(event);
this.progress = event.percent;
if (event.status === UploadStatus.Completed) {
alert(`upload complete!`);
}
},
(err) => {
console.log(err);
},
() => {
this.isUploading = false;
console.log('complete');
},
);
}
// Do something you want when file error occur.
alertError(msg: FileError) {
switch (msg) {
case FileError.NumError:
alert('Number Error');
break;
case FileError.SizeError:
alert('Size Error');
break;
case FileError.TypeError:
alert('Type Error');
break;
}
}
}
API
Attribute Detail
Attribute | necessary(default) | type | position | description |
---|---|---|---|---|
(ngxf-select) | yes | (Array)=>File or FileError | any tag | provide a directive that can let you select file upload by click |
(ngxf-drop) | yes | (Array)=>File[] or FileError | any tag | provide a directive for you to set area can be drop file into |
(ngxf-parse) | yes | (Array)=>File[] or FileError | any tag | provide a directive for you to set area can be parse file into |
[ngxf-validate] | no | FileOption | with (ngxf-drop) and (ngxf-select) | file validate with file size, and other options |
[drop-class] | no('drop') | string | with (ngxf-drop) and (ngxf-select) | when drop on tag, this class will append on it |
[accept] | no | string | with (ngxf-drop) and (ngxf-select) | accept file type |
[multiple] | no | boolean | with (ngxf-drop) and (ngxf-select) | is allow multiple file |
[folder] | no | boolean | (ngxf-select) | is allow select folder file |
[structure] | no | boolean | (ngxf-drop) | show the structure of all folders and files with the new feature of dragging folders. |
Service Upload Method
This method will return an Observable<UploadEvent>
, that you can subscribe it, and return a UploadEvent.
upload(d: UploadObject): Observable<UploadEvent>;
Upload Object
export interface UploadObject {
/** target upload api url */
url: string;
/** upload file or files, also support Blob */
files: File | File[] | Blob | Blob[];
/**
* target file key name
*
* @default
* 'file'
*/
filesKey?: string | string[];
/** is that need report upload progress,
*
* @default
* false
*/
process?: boolean;
/** other fields that you want to attach together */
fields?: any;
/** other headers that you want to attach together */
headers?: { [name: string]: string | string[] } | HttpHeaders;
/** other params that you want to attach together */
params?: { [name: string]: string | string[] } | HttpParams;
/** response type */
responseType?: 'arraybuffer' | 'blob' | 'json' | 'text';
/**
* is that with credentials
*
* view more:
*
* https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
*/
withCredentials?: boolean;
/**
* request api method type,
*
* @default
* POST
*/
method?: string;
}
Return Object
You can use this object when event return.
export interface UploadEvent {
/**
* upload status
*
* - `UploadStatus.Uploading`
* - `UploadStatus.Completed`
* - `UploadStatus.UploadError`
* - `UploadStatus.FileNumError`
*/
status: UploadStatus;
/** what percent of current upload rate */
percent: number;
/** other data you want to attach */
data?: any;
}
FileOption
export interface FileOption {
/**
* check upload file size
* unit: `Byte`
*/
size?: {
/** the smallest bytes */
min?: number;
/** the biggest bytes */
max?: number;
}; // unit: Byte,
/**
* when you upload some files in once, but not throw error when have some file not in the range
* you can set it to true, let will skip the Invalid file
*
* @default false
*/
skipInvalid?: boolean;
}
FileError
You can use this enum to conclude the file select return.
export const enum FileError {
/** when number of file Error */
NumError,
/** when file accept type Error */
TypeError,
/** when file size error */
SizeError,
}
UploadStatus
You can use this enum to conclude the return Event.
export const enum UploadStatus {
/** when file is uploading. */
Uploading,
/** when upload complete. */
Completed,
/** when server error. */
UploadError,
/** when no choice file. */
FileNumError,
}