ngx-uploader is not working on Angular 16 app

Discussão em 'Angular' iniciado por Youssera Zoukha MECIFI, Novembro 4, 2024.

  1. I'm trying to create a sophisticated file uploader using Angular 16 frontend with a Laravel 11 backend, and i searched and found that ngx-uploader is suitable for the options i need in my file uploader (using drag-and-drop and file browser, showing uplaod progress bar, total number of files and how many been uploaded so far, list of succesfully uploaded files) but i dont seem to be able to make it work for some reason i find it complicated

    i tried different things, like modifying, my component code; the interfaces.d.ts code, i also looked for tutrials but nothing helped, let me share my code with you :

    <app-alert></app-alert>
    <div class="container">
    <div class="row py-5">
    <div class="col-lg-12">
    <div class="upload-container">
    <h2>{{('Upload.Upload' | translate)}}</h2>

    <!-- Drop Container -->
    <div class="drop-container" ngFileDrop [options]="options" (uploadOutput)="onUploadOutput($event)"
    [uploadInput]="uploadInput" [ngClass]="{ 'is-drop-over': dragOver }">
    <div class="upload-icon">
    <img src="assets/imgs/Upload icon.svg" alt="Upload Icon">
    </div>
    <h3>{{('Upload.Drag & drop files or' | translate)}}
    <label class="browse-link" (click)="onBrowseClick()">{{('Upload.Browse' | translate)}}</label>
    </h3>
    <p class="supported-formats">{{('Upload.Supported formats: PDF, Word and PPT' | translate)}}</p>
    <input type="file" #fileInput ngFileSelect [options]="options" (uploadOutput)="onUploadOutput($event)"
    [uploadInput]="uploadInput" multiple hidden />
    </div>

    <!-- Completed Upload Count -->
    <div class="upload-status">
    Uploading - {{ completedUploads }}/{{ files.length }} files
    </div>


    <!-- File List with Progress and Error Messages -->
    <div class="file-list">
    <h3 *ngIf="files.length>0">Uploaded</h3>
    <div *ngFor="let file of files" class="file-item"
    [ngClass]="{'error': file.errorStatus, 'success': file.progress?.status === UploadStatus.Done}">
    <span>{{ file.name }}</span>
    <!-- Remove button for each file -->
    <button class="remove-btn" (click)="removeFile(file.id)">
    <i class="bi bi-trash3"></i>
    </button>
    <!-- Display progress for each file -->
    <div *ngIf="file.progress?.status === UploadStatus.Uploading" class="progress-bar">
    <div class="progress" [style.width.%]="file.progress?.data?.percentage"></div>
    <span>{{ file.progress?.data?.percentage }}%</span>
    </div>
    <!-- Error message in red if there's an error -->
    <span *ngIf="file.errorStatus" class="error-message">
    {{ file.errorMessage || 'Upload failed'}}
    </span>
    </div>

    </div>

    <!-- Upload Button -->
    <app-button-green (click)="startUpload()">Upload File</app-button-green>
    </div>
    </div>
    </div>
    </div>



    here is my ts file:

    import { HttpClient } from '@angular/common/http';
    import { Component, ElementRef, EventEmitter, ViewChild } from '@angular/core';
    import { UploadOutput, UploadInput, UploadFile, UploaderOptions, UploadStatus } from 'ngx-uploader';
    import { ProfileUpdateService } from 'src/app/services/profile-update.service';
    import { environment } from 'src/environments/environment.development';

    @Component({
    selector: 'app-upload-file',
    templateUrl: './upload-file.component.html',
    styleUrls: ['./upload-file.component.css']
    })
    export class UploadFileComponent {
    options: UploaderOptions;
    files: UploadFile[] = [];
    uploadInput: EventEmitter<UploadInput>;
    dragOver?: boolean;
    uploadUrl = `${environment.apiUrl}/upload_files`; // Adjust your API URL as needed
    @ViewChild('fileInput') fileInput!: ElementRef; // Reference to the file input
    completedUploads: number = 0;
    user_id=0;
    public UploadStatus = UploadStatus; // Make UploadStatus available in template

    constructor(private userService: ProfileUpdateService) {
    this.options = { concurrency: 1, maxUploads: 3, maxFileSize: 1000000, allowedContentTypes:['.pdf','.docx','.pdf','.pptx'] }; // Adjust options based on needs
    this.uploadInput = new EventEmitter<UploadInput>(); // Initialize the event emitter
    this.fetchUserId();
    }

    fetchUserId(): void {
    this.userService.getUser().subscribe(response => {
    this.user_id = response.id; // Store user ID in a class variable
    });
    }

    onUploadOutput(output: UploadOutput): void {
    switch (output.type) {
    case 'addedToQueue':
    if (typeof output.file !== 'undefined') {
    this.files.push(output.file);
    }
    break;

    case 'allAddedToQueue':
    this.startUpload(); // Start the upload process after adding files
    break;

    case 'uploading':
    if (typeof output.file !== 'undefined') {
    // update current data in files array for uploading file
    const index = this.files.findIndex(file => typeof output.file !== 'undefined' && file.id === output.file.id);
    this.files[index] = output.file;
    }
    break;

    case 'removed':
    // remove file from array when removed
    this.files = this.files.filter((file: UploadFile) => file !== output.file);
    break;
    case 'dragOver':
    this.dragOver = true;
    break;
    case 'dragOut':
    case 'drop':
    this.dragOver = false;
    break;
    case 'done':
    // The file is downloaded
    break;

    }
    }

    updateCompletedUploads() {
    this.completedUploads = this.files.filter(file => file.progress?.status === UploadStatus.Done).length; // Count completed uploads
    }

    startUpload(): void {
    const uploadEvent: UploadInput = {
    type: 'uploadAll',
    url: this.uploadUrl,
    method: 'POST',
    user_id: this.user_id
    };
    this.uploadInput.emit(uploadEvent); // Emit the upload event
    }

    removeFile(id: string): void {
    this.files = this.files.filter(file => file.id !== id); // Remove file from list
    this.updateCompletedUploads(); // Update completed uploads count
    }

    onBrowseClick(): void {
    this.fileInput.nativeElement.click(); // Trigger the hidden file input
    }
    }



    here is the interfaces file:

    import { Subscription } from 'rxjs';

    export interface UploaderOptions {
    concurrency: number;
    allowedContentTypes?: string[];
    maxUploads?: number;
    maxFileSize?: number;
    }

    export interface BlobFile extends Blob {
    name: string;
    }

    export declare enum UploadStatus {
    Queue = 0,
    Uploading = 1,
    Done = 2,
    Cancelled = 3
    }

    export interface UploadProgress {
    status: UploadStatus;
    data?: {
    percentage: number;
    speed: number;
    speedHuman: string;
    startTime: number | null;
    endTime: number | null;
    eta: number | null;
    etaHuman: string | null;
    };
    }

    export interface UploadFile {
    id: string;
    fileIndex?: number;
    lastModifiedDate?: Date;
    name?: string;
    file_size?: number;
    type?: string;
    form?: FormData;
    progress?: UploadProgress;
    response?: any;
    responseStatus?: number;
    sub?: Subscription | any;
    nativeFile?: File;
    responseHeaders?: {
    [key: string]: string;
    };
    errorStatus?: boolean; // Add this line
    errorMessage?: string; // Add this if you need an error message
    }

    export interface UploadOutput {
    type: 'addedToQueue' | 'allAddedToQueue' | 'uploading' | 'done' | 'start' | 'cancelled' | 'dragOver' | 'dragOut' | 'drop' | 'removed' | 'removedAll' | 'rejected';
    file?: UploadFile;
    nativeFile?: File;
    }

    export interface UploadInput {
    type: 'uploadAll' | 'uploadFile' | 'cancel' | 'cancelAll' | 'remove' | 'removeAll';
    url?: string;
    method?: string;
    id?: string;
    fieldName?: string;
    fileIndex?: number;
    user_id?: number;
    file?: UploadFile;
    data?: {
    [key: string]: string | Blob;
    };
    headers?: {
    [key: string]: string;
    };
    includeWebKitFormBoundary?: boolean;
    withCredentials?: boolean;
    }



    and here is my laravel function :

    public function upload(UploadedFileRequest $request)
    {

    try {
    // Initialize an array to hold the paths of uploaded files
    $filePaths = [];

    if ($request->hasfile('filePaths')) {
    $count = 0;
    foreach ($request->file('filePaths') as $file) {
    $f = new UploadedFile();
    $f->user_id = $file->user_id;
    $f->file_size = $file->file_size;

    $fileName = str_replace(' ', '', $file->getClientOriginalName() . '(' . time() . ').' . $file->getClientOriginalExtension());
    $f->file_path = $file->storeAs('uploadedFiles', $fileName);
    $f->save();
    $count++;
    $filePaths[] = $f->file_path;
    }
    }

    // Return a successful response with the file paths
    return response()->json([
    'message' => __('exceptions.Files uploaded successfully'),
    'paths' => $filePaths,
    ]);
    } catch (Error $e) {
    Log::error('Error: ' . $e->getMessage());
    return response()->json([__('validation.error') => $e->getMessage()], 422);
    } catch (\Throwable $e) {
    Log::error('Error: ' . $e->getMessage());
    return response()->json([__('validation.error') => $e->getMessage()], 422);
    } catch (\Exception $e) {
    Log::error('Error: ' . $e->getMessage());
    return response()->json([__('validation.error') => $e->getMessage()], 422);
    }
    }

    Continue reading...

Compartilhe esta Página