Learn AspNet
Learn AspNet

Reputation: 1612

Convert uploaded file to base64 in an angular service

I am trying to convert uploaded csv file to base 64 in an angular service. If I use the same method, it works fine in a component but when I am calling from a service, it gets null value.

Component

public upload(files) {   
      this.uploadedFile = this.service.getBase64(this.file); // This does not work
      // this.getBase64(this.file); // This works if method is in same component
    }
  }

  getBase64() {
    const myReader = new FileReader();
    myReader.onloadend = e => {
      this.uploadedFile = myReader.result.toString().split(',')[1];
    };
    myReader.readAsDataURL(this.file);
  }

This works fine but now when I call the method using service, it does not work

Service

  getBase64(file: any){
    const myReader = new FileReader();
    let base64File: any;
    myReader.onloadend = e => {
      base64File = myReader.result.toString().split(',')[1];
    };
    myReader.readAsDataURL(file);
    return base64File;
  }

Service returns null/undefined value. How can I keep base64 function in a service layer. Service is working correctly as there are multiple functions inside the service.

Upvotes: 1

Views: 1857

Answers (1)

Random
Random

Reputation: 3236

You are using an asynchronous method, and try to return a synchronous data. It works inside the same component because you do not use the return statement, you directly set the new value in its variable (you can replace this.uploadedFile = this.service.getBase64(this.file); with this.service.getBase64(this.file);, it would have the same result since your method does not return anything)

In a different class, you have to use a Subject to be able to subscribe to it:

// Service
uploadedFile$: Subject<string> = new Subject<string>();

updateBase64(file: any) {
  const myReader = new FileReader();
  myReader.onloadend = e => {
    this.uploadedFile$.next(myReader.result.toString().split(',')[1]);
  };
  myReader.readAsDataURL(file);
}

getBase64(): Observable<string> {
  return this.uploadedFile$.asObservable();
}



// Component

base64Subscribtion: Subscribtion;
constructor(public service: MyAppService) {
    this.base64Subscribtion = this.service.getBase64()
        .subscribe(result => this.uploadedFile = result); // receive new value from service when it is ready
}

public upload(files) {   
  this.service.updateBase64(this.file); // asks the service to update its value
}

ngOnDestroy() {
  this.base64Subscribtion.unsubscribe(); // since a Subject never ends, you have to cancel manually subscribtion, otherwise your component will never be able to die (memory leak)
}

Upvotes: 1

Related Questions