Angular6 离子4:录制音频并发送到服务器(文件已损坏)

Angular6 离子4:录制音频并发送到服务器(文件已损坏),angular6,ionic4,form-data,cordova-media-plugin,Angular6,Ionic4,Form Data,Cordova Media Plugin,我想在移动应用程序(iOS和Android)中录制音频文件,并在ionic 4中作为formData传输到服务器。我使用“cordova插件媒体”使用以下逻辑捕获音频 if (this.platform.is('ios')) { this.filePaths = this.file.documentsDirectory; this.fileExtension = '.m4a'; } else if (this.platform.is('android')) {

我想在移动应用程序(iOS和Android)中录制音频文件,并在ionic 4中作为formData传输到服务器。我使用“cordova插件媒体”使用以下逻辑捕获音频

  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();
      });
   }
甚至我也尝试过不使用“文件创建”直接创建媒体

我可以录制和播放音频,但如果我试图发送此文件 使用以下逻辑将无法正确发送到服务器(损坏的数据) 而且web应用程序无法播放.m4a扩展

如果我的代码有任何错误,请纠正我

上传逻辑:

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 - 
     })
)

我使用了Ankush建议的解决方案,效果很好。 使用readAsArrayBuffer而不是readAsDataURL。 .m4a格式支持ios和android。我也能 从web应用程序下载相同的文件


我使用下面的代码将图像上传到服务器。我假设在这段代码中只需要一些修改就可以传输介质而不是图像文件

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))
    );
}
私有上传图片(imagePath:string,apirl:string):可观察{
返回此.convertFileFromFilePathToBlob(imagePath).pipe(
switchMap(item=>this.convertBlobToFormData(item)),
switchMap(formData=>this.postImageToServer(formData,apiUrl))
);
}
上述代码中使用的Rest函数:

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.');
      });
    });
}
private postmagetoserver(formData:formData,apirl:string):可观察{
const requestHeaders=新的HttpHeaders({enctype:'multipart/form data'});
返回this.http.post(apirl,formData,{headers:requestHeaders});
}
私有convertBlobToFormData(blob:blob):可观察{
返回新的可观察对象(订户=>{
//Blob()几乎就是一个文件()-它只是缺少下面我们要添加的两个属性
//tslint:禁用下一行:无字符串文字
blob['lastModifiedDate']=新日期();
//tslint:禁用下一行:无字符串文字
blob['name']='sample.jpeg';
const formData=new formData();
append('file',blob as blob,'sample.jpeg');
下一步(formData);
subscriber.complete();
});
}
私有convertFileFromFilePathToBlob(imagePath:string):可观察{
返回新的可观察对象(订户=>{
const directoryPath=imagePath.substr(0,imagePath.lastIndexOf('/');
让fileName=imagePath.split('/').pop();
fileName=fileName.split(“?”)[0];
this.file.readAsArrayBuffer(directoryPath,fileName)。然后(fileEntry=>{
const imgBlob:any=新Blob([fileEntry],{type:'image/jpeg'});
imgBlob.name='sample.jpeg';
订阅方。下一个(imgBlob);
subscriber.complete();
}, () => {
subscriber.error('从文件路径读取图像时发生错误');
});
});
}

android 3gp扩展用于视频文件谢谢。它很好用。我使用了readAsArrayBuffer而不是readAsDataURL。