angular6ionic4form-datacordova-media-plugin

Ionic 4 : Recording Audio and Send to Server (File has been corrupted)


I would like to record the audio file in mobile application(iOS & Android) and tranfer to server as a formData in ionic 4. I have used the "cordova-plugin-media" to capture the audio using below logics

  if (this.platform.is('ios')) {
      this.filePaths = this.file.documentsDirectory;
      this.fileExtension = '.m4a';
    } else if (this.platform.is('android')) {
      this.filePaths = this.file.externalDataDirectory;
      this.fileExtension = '.3gp';
    }

  this.fileName = 'recording'+new Date().getHours()+new Date().getMinutes()+new Date().getSeconds()+this.fileExtension;

    if(this.filePaths) {
this.file.createFile(this.filePaths,this.fileName,true).then((entry:FileEntry)=> {
        this.audio = this.media.create(entry.toInternalURL());
        this.audio.startRecord();
      });
   }

Even I have tried to create the media directly without "File Creation"

I can record and play the audio, but If I am trying to send this file to server using below logics It won't send properly(corrupted data) and also web application unable to play .m4a extensions

.

Please correct me If I am doing anything wrong in my code

Upload logic:

let formData:FormData = new FormData();
 formData.append('recordID' , feedbackID);
  that.file.readAsDataURL(filePath,file.name).then((data)=>{
       const audioBlob = new Blob([data], { type: file.type });
       formData.append('files', audioBlob, file.name);
       that.uploadFormData(formData,feedbackID); //POST Logics - 
     })

;

I have used the soultion as suggested by Ankush and it works fine. Used readAsArrayBuffer instead of readAsDataURL. The .m4a format has supported both ios and android. Also I can download the the same file from web application.


Solution

  • I am using below code to upload the image to the server. I assume that only a few modifications will be required in this code to transfer media instead of the image file.

    private uploadPicture(imagePath: string, apiUrl: string): Observable<ApiResponse<ImageUploadResponseModel>> {
    
        return this.convertFileFromFilePathToBlob(imagePath).pipe(
          switchMap(item => this.convertBlobToFormData(item)),
          switchMap(formData => this.postImageToServer(formData, apiUrl))
        );
    }
    

    Rest functions used in above code:

    private postImageToServer(formData: FormData, apiUrl: string): Observable<ApiResponse<ImageUploadResponseModel>> {
        const requestHeaders = new HttpHeaders({ enctype: 'multipart/form-data' });
        return this.http.post<ApiResponse<ImageUploadResponseModel>>(apiUrl, formData, { headers: requestHeaders });
    }
    
    private convertBlobToFormData(blob: Blob): Observable<FormData> {
        return new Observable<FormData>(subscriber => {
          // A Blob() is almost a File() - it's just missing the two properties below which we will add
          // tslint:disable-next-line: no-string-literal
          blob['lastModifiedDate'] = new Date();
          // tslint:disable-next-line: no-string-literal
          blob['name'] = 'sample.jpeg';
          const formData = new FormData();
          formData.append('file', blob as Blob, 'sample.jpeg');
          subscriber.next(formData);
          subscriber.complete();
        });
    }
    
    private convertFileFromFilePathToBlob(imagePath: string): Observable<Blob> {
        return new Observable<Blob>(subscriber => {
          const directoryPath = imagePath.substr(0, imagePath.lastIndexOf('/'));
          let fileName = imagePath.split('/').pop();
          fileName = fileName.split('?')[0];
          this.file.readAsArrayBuffer(directoryPath, fileName).then(fileEntry => {
              const imgBlob: any = new Blob([fileEntry], { type: 'image/jpeg' });
              imgBlob.name = 'sample.jpeg';
              subscriber.next(imgBlob);
              subscriber.complete();
          }, () => {
            subscriber.error('Some error occured while reading image from the filepath.');
          });
        });
    }