angularfire icon indicating copy to clipboard operation
angularfire copied to clipboard

uploadTask.on('state_changed') Has incorrect UploadTaskSnapshot type data

Open mingmod opened this issue 2 years ago • 0 comments

Version info

Angular: "@angular/core": "15.1.2",

Firebase: "firebase": "9.16.0",

AngularFire: "@angular/fire": "7.5.0",

Other (e.g. Ionic/Cordova, Node, browser, operating system): Windows 11, Node v18.18.0, Chrome Version 117.0.5938.132 (Official Build)

How to reproduce these conditions

I got an issue when uploading big files (ex 1mb). When I am uploading some small file in the end I get correct UploadTaskSnapshot object which one have correct metadata (FullMetadata type) field see screenshot below image

But when I am trying to upload a file a little bit bigger (1661KB) I have this output image it's having partial FullMetadata type fields

upload(options: UploaderOptions): Observable<UploadTask> {
    const {
      file,
      colIndexes = [],
      isHeaders = false,
      delimiter = ',',
    } = options;

    if (!this.auth || !this.auth.currentUser) {
      return throwError(() => new Error('user is not signed in'));
    }

    if (colIndexes.length === 0) {
      return throwError(() => new Error('column indexes is not specified'));
    }

    return new Observable((observer) => {
      const responseHandler = ({
        buffer,
        linesCount = 0,
      }: CsvCollectorSuccessResult): void => {
        if (!buffer) {
          observer.error(new Error('result buffer is undefined'));
          return;
        }

        const uploadData = new Uint8Array(buffer as Uint8Array);

        const { id } = doc(collection(this.db, 'files'));
        const uid = this.authService.getUid();
        const fileRef = ref(this.storage, `/${uid}/csv/${id}.csv`);

        const uploadTask = uploadBytesResumable(fileRef, uploadData, {
          contentType: 'text/csv',
          contentDisposition: `attachment;filename*=UTF-8''${encodeFilename(
            this.getFileName(file)
          )}`,
          customMetadata: {
            lang: this.langService.getCurrentLang(),
            uid,
            delimiter,
            linesCount: linesCount.toString(),
            fileName: this.getFileName(file),
          },
        });
        console.log(uploadTask, observer);
        observer.next(uploadTask);
        observer.complete();
      };

      const stepErrorsHandler = (errors): void =>
        observer.error(errors[0] || new Error('error parsing file rows'));

      const closeWorkerHandler = (): void => observer.complete();

      // Start WebWorker

      const collector = new Worker(this.csvCollectorWorkerConfig.scriptPath);

      const handlers = {
        [CsvCollectorMessages.RESULT_BYTES_RESPONSE]: responseHandler,
        [CsvCollectorMessages.INVALID_ROW]: stepErrorsHandler,
        [CsvCollectorMessages.CLOSE_WORKER]: closeWorkerHandler,
      };

      collector.onerror = (e: ErrorEvent) => {
        observer.error(new Error((e && e.message) || 'error has occurred'));
      };

      collector.onmessage = (e: MessageEvent) => {
        const { type, payload } = e.data;
        !!handlers[type]
          ? handlers[type](payload)
          : observer.error(new Error('no message handler was found'));
      };

      // tslint:disable-next-line
      collector.postMessage(
        new WorkerMessage(CsvCollectorMessages.START_JOB, {
          file,
          colIndexes,
          isHeaders,
          delimiter,
        } as UploaderOptions)
      );
    });
  }
this.uploaderService
  .upload({
    file: this.file,
    colIndexes: Array.from(this.checkedColumns, Number),
    delimiter: this.delimiter || ',',
    isHeaders: false,
  } as UploaderOptions)
  .pipe(
    untilDestroyed(this),
    switchMap(
      (uploadTask: UploadTask): Observable<UploadTaskSnapshot> =>
        new Observable((observer) => {
          return uploadTask.on('state_changed', {
            next: (data) => observer.next(data),
            error: (error) => observer.error(error),
            complete: () => observer.complete(),
          });
        })
    ),
    tap((uploadSnapshot) => {
      console.log('uploadSnapshot', uploadSnapshot.metadata);
    })
  )

Failing test unit, Stackblitz demonstrating the problem

Steps to set up and reproduce

Sample data and security rules

Debug output

** Errors in the JavaScript console **

** Output from firebase.database().enableLogging(true); **

** Screenshots **

Expected behavior

Actual behavior

mingmod avatar Oct 04 '23 10:10 mingmod