File upload progress within each row in angular

Viewed 60

I am trying to show the upload progress when uploading multiple files into the cloud. I can track all the data progress status of the file upload and can display it within the HTML. I have tried some code like the below.

upload.component.html

<div class="upload-table">
    <table class="table">
      <thead>
        <tr>
          <th scope="col">Name</th>
          <th scope="col">File Size</th>
          <th>Upload Status</th>
        </tr>
      </thead>
      <tbody class="upload-name-style">
        <tr *ngFor="let item of files; let i = index" id="{{ i }}">
          <td>
            <strong>{{ item.name }}</strong>
          </td>
          <td>
            <strong>{{ item.size | filesize }}</strong>
          </td>
          <td>
            <span *ngIf="uploading"
              ><i class="fas fa-spinner fa-pulse"></i></span
            >**{{ uploadStatus }}**
          </td>
        </tr>
      </tbody>
    </table>
  </div>

uploadFiles method within the upload component

upload.component.ts

export class UploadComponent {

  @Output() parentRecord: any;
  @Output() updatedParentRecordEvent = new EventEmitter<any>();

  fileSelected = false;
  uploading: boolean;
  uploadSuccess: boolean;
  progressText: string;
  buttonText: string;

  sessionUploadURL: string;


  files: File[] = [];
  fileList: any[] = [];

  sessionUrls: any[] = [];
  selelctedFiles: any[] = [];
  fileSessionUrls: string[] = [];

  itemId = env.azure.itemId;

  uploadStatus: string;
  fileIndex: number;

  constructor(
    // private fileUpload: UploadFileService,
    private ms_graph: MSGraphService,
    private changeDetection: ChangeDetectorRef,
    private toastr: ToastrService
  ) {}

  ngOnInit(): void {
    this.progressText = 'Drop your files here or Click...';
    this.buttonText = 'Browse Files';
  }

  // New method of file upload into JUICE folder
  // onBrowse & onFileDrop methods needs to keep seperatly, due to the different methods of file selection from the file source.
  onBrowse(event: any) {
    this.files = <File[]>event.target.files;
    this.fileSelect(this.files);
    this.fileList.push(this.files);
    // console.log(this.fileList);
  }

  onFileDrop(event: any) {
    this.files = <File[]>event;
    this.fileSelect(this.files);
    this.fileList.push(this.files);
    // console.log(this.fileList);

  }

  public fileSelect(files: File[]) {
    if (this.files.length > 0) {
      console.log(this.files);
      this.fileSelected = true;
      this.progressText = this.files.length + ' File(s) selected. Click to upload.';
      this.buttonText = 'Upload Files';
      this.uploadStatus = "Pending..."
    }
  }

  onUpload() {
    this.uploading = true;
    this.progressText = "Upload Pending";
    // this.fileList.push(this.uploading);
    // console.log(this.fileList);

    // this.uploadFile(this.files);
    // this.progressText = 'Drop your files here or Click...';
    // this.uploadStatus = "Pending...";
  }

  // Creating a session folder is not required due to save all files into JUICE folder which is already defined

  async uploadFile(files: File[]) {
    for (let file of files) {
      console.log(file.name);
      let fileNameArray = file.name.lastIndexOf('.');
      let fileType = file.name.substring(fileNameArray + 1);
      let fileName = file.name.substring(0, fileNameArray);

      this.progressText = 'Creating session...';
      this.ms_graph.currentFileStatusMessage.subscribe((status) => {
        this.progressText = status;
        this.changeDetection.detectChanges();
      });
      this.ms_graph.currentEventStatusMessage.subscribe((status) => {
        this.buttonText = status;
        this.changeDetection.detectChanges();
      });
      this.ms_graph.uploadingStatus.subscribe((status) => {
        this.uploading = status;
        this.changeDetection.detectChanges();
      });
      this.ms_graph.uploadSuccessStatus.subscribe((status) => {
        this.uploadSuccess = status;
        // if(this.uploadSuccess == true) {
        //   this.toastr.success('File Upload Successfully', 'Upload Complete', {closeButton: true});
        // }
      });
      this.sessionUrls.push(
        this.ms_graph.get_upload_session(fileType, fileName, this.itemId)
      );
      this.selelctedFiles.push(file);
    }
    forkJoin(this.sessionUrls).subscribe(async (response: any) => {
      for(let i = 0; i<response.length; i++) {
        this.sessionUploadURL = response[i].uploadUrl;
        this.fileSessionUrls.push(this.sessionUploadURL);
      }
      await this.uploadFiles(this.fileSessionUrls, this.selelctedFiles)
      // this.uploading = false;
    })
  }
  async uploadFiles(urls: any[], files: any[]){
    for (let i = 0; i < urls.length; i++) {
      let url = urls[i];
      let file = files[i];
      await this.ms_graph.upload_chunks(file, url);
      this.fileIndex = i;
    }
    this.fileSelected = false;
  }
}

When the for loop is executed, "{{ uploadStatus }}" of the upload.component.html must change like the below image. enter image description here

But I only want to display the current progress of each file separately, others must remain pending status until it starts to upload. When the upload is finished, "{{uploadStatus}}" will change to "Complete! (view file)". an example image is below.

enter image description here

Can someone suggest an option to do it?

1 Answers

You want to show the uploading statuses of each file but you're using 2 variables in your HTML which I can't see where you set or updated.

<td>
   <span *ngIf="uploading"
     ><i class="fas fa-spinner fa-pulse"></i></span
      >**{{ uploadStatus }}**
</td>

should be something like

<td>
  <span *ngIf="item.uploading"
   ><i class="fas fa-spinner fa-pulse"></i></span
   >**{{ item.uploadStatus }}**
</td>

and you need to update those properties in your uploadFiles function.

Like:

async uploadFiles(urls: any[]){
for (let i = 0; i < urls.length; i++) {
  this.files[i] = {...this.files[i], uploading:true, 
   uploadStatus:"Started"};
  await this.ms_graph.upload_chunks(urls[i], this.files[i]);
  this.files[i] = {...this.files[i], uploading:false, 
  uploadStatus:"Complete!"};
  this.fileIndex = i;
}
this.fileSelected = false;

}

of course, you need to set the initial uploadStatuses of each file as 'Pending'.

Related