You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Ionic+Angular+Cordova的音频文件上传至服务器问题排查

问题描述

我正在尝试使用Ionic、Angular和Cordova,将通过MediaObject创建的音频文件上传至服务器,使用了Native File插件和@angular/common/http中的HttpClient。

服务器端无法通过PHP $_FILES['audio']获取到文件,我无法排查出问题所在,或许需要使用file.getFile()来获取文件,但尝试后并未成功。

我已经尝试将Content-Type设置为"multipart/form-data"、"file"、"false"、"undefined",但服务器端仍无法获取文件。

以下是我的代码,已引入所有必要依赖,控制台无报错:

audio: MediaObject;
audioFile: FileEntry;
fileName: string;


startAudio() {
    
    this.fileName = "audio" + Date.now() + ".mp3";
    this.audio = this.media.create(this.fileName);
    this.audio.startRecord();
  
}

async finishAudio(){
    this.audio.stopRecord();
    
    const formAudio = new FormData();
    
    //this.audioFile = this.file.getFile(this.file.externalDataDirectory.replace(/file:\/\//g, ''), this.fileName, { create: false });
    
    const buffer = await this.file.readAsArrayBuffer(this.file.externalDataDirectory, this.fileName);   
    const fileBlob = new Blob([buffer], {type:'audio/mp3'});
    console.log(buffer);
    formAudio.append("audio", fileBlob, this.fileName);
    this.responseAudioForm = this.audioFormService.postFile(formArchivo);
            this.responseAudioForm.subscribe(data =>{
                this.responseDataAudioForm = data ;
                let title = data.title;
                let message = data.message;
    });
}


/* AudioFormService */

postFile(formData:FormData): Observable<any>{
        //console.log(fields);
        const httpOptions = {
            headers: new HttpHeaders({
                "Content-Type": "application/x-www-form-urlencoded", 
            })
        }
        
        this.presentLoading();
        return this.httpClient.post(this.apiUpdateURL, formData, httpOptions)
            .pipe(
                map(results => {
                    console.log("RAW:",results);
                    this.dismissLoading();
                    this.showToast();
                    return results;
                }),
                catchError(err => {
                    console.log("Handling error:", err);
                    this.showAlert(err.statusText,err.name,err.message);
                    return throwError(err);
                }),
                catchError(err => {
                    console.log("caught rethrown:", err);
                    return of([]);
                }),
            );
}
解决方案(供有需要的开发者参考)
audio: MediaObject;
audioFile: FileEntry;

responseAyudaForm: Observable<any>;
responseDataAyudaForm: any = [];

// Start audio recording
async startAudio() {
    
    var path: string = "";
    if(this.platform.is("ios")){
        
      path = this.file.tempDirectory;
      this.fileName = new Date().getTime() + ".mp3";
      this.audioFile = await this.file.createFile(path, this.fileName, true);
      this.audio = this.media.create(this.file.tempDirectory.replace(/^file:\/\//, '') + this.fileName);
      
    } else {
        
      path = this.file.externalDataDirectory;
      this.fileName = new Date().getTime() + ".mp3";
      this.audioFile = await this.file.createFile(path, this.fileName, true);
      this.audio = this.media.create(this.audioFile.nativeURL);
    
    }

    this.audio.startRecord();
    console.log("Record Start");
}


// Stop audio recording and upload file to server
async finishAudio() {
    
    this.audio.stopRecord();
    console.log("Stop Recording");
    
    // Upload the new recording
    await new Promise(resolve => setTimeout(resolve, 200));
    
    console.log("Start Blob convertion");  
    const blob = await this.getBlobFromFileEntry(this.audioFile);
    console.log("Finish Blob convertion");

    const formFile = new FormData();
        
    formFile.append("audio", blob, this.fileName);
      
    this.responseAyudaForm = this.ayudaService.postFile(formFile);
    this.responseAyudaForm.subscribe(data =>{
        this.responseDataAyudaForm = data ;
        let title = data.title;
        let message = data.message;
    });
  
}

getBlobFromFileEntry(fileEntry: FileEntry): Promise<Blob> {
    
    return new Promise((resolve, reject) => {
        
      fileEntry.file((file) => {
          
        const reader = new FileReader();
        reader.onloadend = function(e) {
            
          
          try {
              
            const { result: buffer } = e.target
            const blob = new Blob( [new Uint8Array(buffer as any)], { type: 'audio/mp3' } /* or file.type */
            
            );
            console.log(blob);
            resolve(blob);
            
          } catch (error) { reject(error); }
          
        };
        
        reader.onabort = (ev) => reject(ev);
        reader.onerror = (ev) => reject(ev);
        reader.readAsArrayBuffer(file);
        
      }, reject)
    });
}

/**
/ AyudaService.postFile()
**/
postFile(formData:FormData): Observable<any>{

    /*const httpOptions = {
        headers: new HttpHeaders({
            "Content-Type": 'file',
        })
    }*/
    
    this.presentLoading();
    return this.httpClient.post(this.apiAudioURL, formData) /* I removed the httpOptions parameter and it worked */
        .pipe(
            map(results => {
                console.log("RAW:",results);
                this.dismissLoading();
                this.showToast();
                return results;
            }),
            catchError(err => {
                console.log("Handling error:", err);
                this.showAlert(err.statusText,err.name,err.message);
                return throwError(err);
            }),
            catchError(err => {
                console.log("Caught Rethrown:", err);
                return of([]);
            }),
        );
}

内容的提问来源于stack exchange,提问作者Nacho Cano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:45:33