Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase 'bytesTransferred': Property 'bytesTransferred' does not exist on type 'Object'

What I'm using

  • Angular
  • Firebase

What I have

  • An upload service that allows me to upload to firebase storage and the realtime database
  • This has been working fine for weeks

The Issue

  • This morning it doesn't work.

  • I haven't changed anything to do with this file or it's components

  • The only thing I have changed was a firebase npm install to try get some other nonsense to work

  • This has literally halted my project completely

  • My service now displays the error on build of:

[ts] Property 'bytesTransferred' does not exist on type 'Object'

[ts] Property 'totalBytes' does not exist on type 'Object'.

Argument of type '() => void' is not assignable to parameter of type 'Unsubscribe'. Type 'void' is not assignable to type 'undefined'.

Questions

  • Does anyone know why this error message is displayed all of a sudden?

My Upload Service

import { Injectable, OnDestroy } from '@angular/core';
import { Upload } from './upload';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';
import * as firebase from 'firebase';
import { AuthService } from '../../user/auth.service';
import { Subscription } from 'rxjs/Subscription';

// Routes
import { Router, ActivatedRoute } from '@angular/router';

@Injectable()
export class ProjectsAddService implements OnDestroy {
  private _subscription: Subscription;
  private basePath: string = '/site_photo';
  uploads: FirebaseListObservable<Upload[]>;

  constructor(
    private db: AngularFireDatabase, 
    private authService: AuthService, 
     private router: Router
  ) { }






  getUploads(query = {}) {
    this.uploads = this.db.list(this.basePath, {
      query: query
    });
    return this.uploads
  }


  deleteUpload(upload: Upload) {
    this.deleteFileData(upload.$key)
      .then(() => {
        this.deleteFileStorage(upload.name)
      })
      .catch(error => console.log(error))
  }

  // Writes the file details to the realtime db
  private deleteFileData(key: string) {
    return this.db.list(`${this.basePath}/`).remove(key);
  }

  // Firebase files must have unique names in their respective storage dir
  // So the name serves as a unique key
  private deleteFileStorage(name: string) {
    const storageRef = firebase.storage().ref();
    storageRef.child(`${this.basePath}/${name}`).delete()
  }

  ngOnDestroy() {
    if (this._subscription) {
      this._subscription.unsubscribe();
    }
  }

  submitForm(title: string, reference: string, date: string, auditorName: string, newCompanyName: string, upload: Upload) {
    this._subscription = this.authService.user.subscribe(user => {
      if (user) {

        // The User ID of the current user
        var userId = user.uid;

        // Generate a new firebase key to be used for the Project, Project List, Project Members and Storage References
        var newPostKey = firebase.database().ref().child('project_list').push().key;

        // Create a reference to the firebase storage
        const storageRef = firebase.storage().ref();
        const uploadTask = storageRef.child('site_photo/' + user.uid + '/' + newPostKey + '/site_photo').put(upload.file);

        uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
          (snapshot) => {
            // upload in progress
            upload.progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
          },
          (error) => {
            // upload failed
            console.log(error)
          },
          () => {
            // upload success
            upload.url = uploadTask.snapshot.downloadURL
            upload.name = upload.file.name

            // Data to be added to the 'Project' node
            var albumDetails = {
              album_title: title,
              label_name: newCompanyName,
              album_photo: upload.url
            }

            // Data to be added to the 'Project_list' node
            var albumList = {
              label_name: newCompanyName,
              album_photo: upload.url
            }

            // Data to be added to the 'Project_members' node
            var userList = {
              [userId]: true
            }

            // Group the updates to the associated firebase nodes
            var updates = {};
            updates['/album/' + user.uid + '/' + newPostKey] = projectsDetails;
            updates['/album_list/' + user.uid + '/' + newPostKey] = projectsList;
            updates['/project_members/' + newPostKey] = userList;


            // Once the image has been successfully uploaded, make an update to the realtime database
            this.saveToRealtimeDatabase(updates);

            this.router.navigate(['projects']);
          }
        );

      }

    });


  }

  // Perform an atomic Multi-Path update
  private saveToRealtimeDatabase(updates) {
    return firebase.database().ref().update(updates);
  }


}

Any help here would be HUGELY appreciated. Completely baffed by this.




UPDATE

I've noticed that if I comment out the following code, it compiles correctly. I just get an incorrect reading of the progress of the upload.

          (snapshot) => {
            // upload in progress
            upload.progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
          },
          (error) => {
            // upload failed
            console.log(error)
          },

SECOND UPDATE The following works, but it feels a bit odd. Any help would be appreciated.

        var snapshotRef = snapshot as firebase.storage.UploadTaskSnapshot;
        var bytesTransferred = (snapshotRef).bytesTransferred;
        var totalBytes = (snapshotRef).totalBytes;
        upload.progress = (bytesTransferred / totalBytes) * 100;
like image 642
MegaTron Avatar asked Aug 04 '17 07:08

MegaTron


2 Answers

Replace your code snippet with below code.

uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
  (snapshot) =>  {
    upload.progress = (uploadTask.snapshot.bytesTransferred / uploadTask.snapshot.totalBytes) * 100;
    console.log(upload.progress);
  },
like image 103
Abdul Haseeb Avatar answered Sep 22 '22 23:09

Abdul Haseeb


I don't know enough about typescript or this package to explain exactly what is going on, but at least I can fix it.

Apparently the complete callback in the new version does no longer accept any as a return type, but only undefined. I think it has something to do with the default Unsubscribe that returns undefined. In your code you can fix the error by manually returning undefined in your callback.

() => {
    console.log('upload complete');
    return undefined;
}

Typescript can apparently not infer the type of the snapshot in the first callback, you will need to specify it manually as well, you can use a typecast or you can call a seperate function from your callback.

 console.log((snapshot as firebase.storage.UploadTaskSnapshot).bytesTransferred);

I would appreciate it if someone has a more in depth explanation.

like image 36
Alfred_P Avatar answered Sep 19 '22 23:09

Alfred_P