Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { CommonModule } from '@angular/common';
- import { HttpClient, HttpErrorResponse, HttpEventType } from '@angular/common/http';
- import { Component, computed, inject, input, signal } from '@angular/core';
- import { FormsModule } from '@angular/forms';
- import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
- import { faUpload, faFileAlt, faExclamationTriangle, faCheckCircle, faSpinner, faTimesCircle, faCloudUploadAlt, faTrash, faL, faEraser, faIndianRupeeSign } from '@fortawesome/free-solid-svg-icons';
- import { v4 as uuidv4 } from 'uuid';
- export interface UploadFile {
- file: File;
- uuid: string,
- baseName: string,
- extension: string,
- customName?: string;
- progress: number;
- status: 'pending' | 'uploading' | 'done' | 'error' | 'invalid';
- errorMessage?: string;
- }
- @Component({
- selector: 'app-file-upload',
- standalone: true,
- imports: [FormsModule, FontAwesomeModule, CommonModule],
- templateUrl: `./file-upload.component.html`,
- styles: ``
- })
- export default class FileUploadComponent {
- http = inject(HttpClient);
- ALLOWED_EXTENSIONS = input<string[]>([], { alias: 'allowedExts' });
- MAX_FILE_SIZE_MB = input<number>(5, { alias: 'maxFileSize' });
- cloudUpload = faCloudUploadAlt;
- fileAlt = faFileAlt;
- exclTriangle = faExclamationTriangle;
- checkCircle = faCheckCircle;
- spinner = faSpinner;
- timesCircle = faTimesCircle;
- uploadIcon = faUpload;
- trash = faTrash;
- clear = faEraser;
- files = signal<UploadFile[]>([]);
- isDragging = signal<boolean>(false);
- isUploaded = signal<boolean>(false);
- allowedExtensionsInputList = computed(() => {
- return this.ALLOWED_EXTENSIONS().toString();
- });
- allowedExtensionsStr = computed(() => {
- return this.allowedExtensionsInputList().replaceAll('.', ' ');
- });
- maxFileSize = computed(() => this.MAX_FILE_SIZE_MB() * 1024 * 1024);
- onDragOver(event: DragEvent) {
- event.preventDefault();
- this.isDragging.set(true);
- }
- onDragLeave(event: DragEvent) {
- event.preventDefault();
- this.isDragging.set(false);
- }
- onDrop(event: DragEvent) {
- event.preventDefault();
- this.isDragging.set(false);
- const files = Array.from(event.dataTransfer?.files || []);
- if (files.length) {
- this.addFiles(files);
- }
- }
- addFiles(selected: File[]) {
- const uploads = selected.map(file => this.validateFile(file)).filter(file => file !== null);
- this.files.update(files => [...files, ...uploads]);
- this.isUploaded.set(false);
- }
- removeFile(selected: UploadFile) {
- this.files.update(files => files.filter(f => f.file !== selected.file));
- }
- clearFiles() {
- this.files.set([]);
- this.isUploaded.set(false);
- }
- onFilesSelected(event: Event) {
- const input = event.target as HTMLInputElement;
- const selected = Array.from(input.files || []);
- this.addFiles(selected);
- }
- validateFile(file: File): UploadFile | null {
- const lastDotIndex: number = file.name.lastIndexOf('.');
- const baseName: string = file.name.substring(0, lastDotIndex);
- const extension: string = file.name.substring(lastDotIndex).toLowerCase();
- const newFile: UploadFile = { file, uuid: uuidv4(), baseName, extension, customName: file.name, progress: 0, status: 'pending', errorMessage: '' };
- if (!this.ALLOWED_EXTENSIONS().includes(extension)) {
- return { ...newFile, status: 'invalid', errorMessage: 'Estensione non consentita' };
- }
- if (file.size > this.maxFileSize()) {
- return { ...newFile, status: 'invalid', errorMessage: `File troppo grande (max ${this.MAX_FILE_SIZE_MB()}MB)` };
- }
- if (this.files()
- .some(existing =>
- existing.baseName === baseName &&
- existing.extension === extension &&
- existing.file.size === file.size
- ))
- return null;
- return newFile;
- }
- updateCustomName(upload: UploadFile) {
- upload.customName = `${upload.baseName}${upload.extension}`;
- }
- sanitizeBaseName(upload: UploadFile) {
- const ext = upload.extension.toLowerCase();
- const extPattern = new RegExp(`${ext.replace('.', '\\.')}`, 'gi');
- upload.baseName = upload.baseName.replace(extPattern, '');
- upload.baseName = upload.baseName.replace(/[\\/:*?"<>|]/g, '');
- upload.baseName = upload.baseName.trim();
- this.updateCustomName(upload);
- }
- uploadAll() {
- this.files().filter(f => f.status === 'pending').forEach(file => this.uploadFile(file));
- this.isUploaded.set(true);
- }
- uploadFile(upload: UploadFile) {
- this.updateCustomName(upload);
- const formData = new FormData();
- formData.append('files', upload.file);
- formData.append('path', '');
- formData.append('saveAs', upload.customName!);
- upload.status = 'uploading';
- this.http.post('http://localhost:7777/api/upload/files', formData, {
- reportProgress: true,
- observe: 'events'
- }).subscribe({
- next: (event) => {
- if (event.type === HttpEventType.UploadProgress && event.total) {
- upload.progress = Math.round(100 * event.loaded / event.total);
- } else if (event.type === HttpEventType.Response) {
- upload.status = 'done';
- }
- },
- error: (err: HttpErrorResponse) => {
- upload.status = 'error';
- upload.errorMessage = err.error;
- console.error(err);
- }
- });
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement