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

使用Media Capture Cordova插件录制/选视频并上传远程服务器遇异常

解决Cordova视频预览与上传的问题

我来帮你搞定这个头疼的问题!从你的代码来看,核心问题出在Cordova本地文件路径的处理以及视频文件的上传方式上,咱们一步步拆解解决:

一、先搞定视频预览的问题

你当前用的是MediaFile的fullPath属性,但这个路径在不同平台(iOS/Android)的格式并不统一,而且直接绑定到video标签会因为安全策略或者路径格式问题被拦截。

修复步骤:

  1. 改用localURL替代fullPath
    Cordova的MediaFile对象提供了localURL属性,这是标准的file://协议路径,跨平台兼容性更好,能被WebView正确识别。

    修改你的takeVideo方法:

    takeVideo() { 
      let options: CaptureVideoOptions = { limit: 1, duration: 15 } 
      this.mediaCapture.captureVideo(options)
        .then( (data: MediaFile[]) => { 
          // 改用localURL,并且直接处理安全信任
          const safeVideoUrl = this.sanitizer.bypassSecurityTrustResourceUrl(data[0].localURL);
          alert(data[0].localURL);
          this.dispVideos.push(safeVideoUrl);
        }, (err: CaptureError) => { 
          // 更友好的错误提示
          alert(err.message || JSON.stringify(err)) 
        }); 
    }
    
  2. 调整HTML的video标签绑定
    因为已经提前处理了安全信任,直接绑定数组元素即可:

    <div *ngIf="dispVideos?.length > 0">
      <video #myVideo preload="metadata" controls>
        <source [src]="dispVideos[0]" type="video/mp4">
      </video>
    </div>
    
  3. 检查Content-Security-Policy(CSP)
    如果还是无法预览,需要在index.html的meta标签中允许本地文件访问:

    <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: cdvfile://* file://* 'unsafe-inline' 'unsafe-eval'; media-src *;">
    

二、解决视频上传的问题

直接传文件路径给服务器是不行的,服务器无法识别本地路径,必须把文件转换成Blob或者FormData格式上传。这里给你两种常用方案:

方案1:用传统的FileTransfer插件(兼容性好)

首先确保安装插件:

cordova plugin add cordova-plugin-file-transfer

然后修改代码实现上传:

// 先注入依赖
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer/ngx';
import { File } from '@ionic-native/file/ngx';

constructor(
  private mediaCapture: MediaCapture, 
  private sanitizer: DomSanitizer, 
  private transfer: FileTransfer, 
  private file: File
) {}

takeVideo() { 
  let options: CaptureVideoOptions = { limit: 1, duration: 15 } 
  this.mediaCapture.captureVideo(options)
    .then( (data: MediaFile[]) => { 
      const videoFile = data[0];
      const fileTransfer: FileTransferObject = this.transfer.create();
      
      // 配置上传参数
      const uploadOptions: FileUploadOptions = {
        fileKey: 'video', // 服务器接收文件的字段名
        fileName: videoFile.name,
        mimeType: 'video/mp4',
        chunkedMode: false,
        params: { /* 可以添加额外的参数,比如用户ID等 */ }
      };

      // 执行上传
      fileTransfer.upload(videoFile.localURL, 'https://你的服务器上传地址', uploadOptions)
        .then((res) => {
          alert('视频上传成功!');
          console.log('服务器响应:', res.response);
        }, (err) => {
          alert('上传失败:' + err.message);
          console.error(err);
        });

      // 同时处理预览
      this.dispVideos.push(this.sanitizer.bypassSecurityTrustResourceUrl(videoFile.localURL));
    }, (err: CaptureError) => { 
      alert(err.message || JSON.stringify(err)) 
    }); 
}

方案2:用HttpClient读取Blob上传(更现代)

如果不想用已标记为废弃的FileTransfer,可以用File插件读取文件为Blob,再通过FormData上传:

// 注入File和HttpClient
import { File } from '@ionic-native/file/ngx';
import { HttpClient } from '@angular/common/http';

constructor(
  private mediaCapture: MediaCapture, 
  private sanitizer: DomSanitizer, 
  private file: File,
  private http: HttpClient
) {}

takeVideo() { 
  let options: CaptureVideoOptions = { limit: 1, duration: 15 } 
  this.mediaCapture.captureVideo(options)
    .then( (data: MediaFile[]) => { 
      const videoFile = data[0];
      // 解析文件的目录和文件名
      const filePath = videoFile.fullPath;
      const fileName = videoFile.name;
      const directory = filePath.substring(0, filePath.lastIndexOf('/'));

      // 读取文件为Blob
      this.file.readAsBlob(directory, fileName)
        .then(blob => {
          const formData = new FormData();
          formData.append('video', blob, fileName);

          // 发送上传请求
          this.http.post('https://你的服务器上传地址', formData, {
            headers: { 'Accept': 'application/json' }
          }).subscribe(
            res => {
              alert('上传成功!');
              console.log(res);
            },
            err => {
              alert('上传失败:' + err.message);
              console.error(err);
            }
          );
        })
        .catch(fileErr => {
          alert('读取本地文件失败:' + fileErr.message);
          console.error(fileErr);
        });

      // 处理预览
      this.dispVideos.push(this.sanitizer.bypassSecurityTrustResourceUrl(videoFile.localURL));
    }, (err: CaptureError) => { 
      alert(err.message || JSON.stringify(err)) 
    }); 
}

最后要注意的细节

  • 确保安装了所有必要插件:cordova-plugin-media-capture、cordova-plugin-file,用FileTransfer的话还要cordova-plugin-file-transfer
  • 权限配置:
    • Android:在AndroidManifest.xml中添加CAMERA、RECORD_AUDIO、WRITE_EXTERNAL_STORAGE权限
    • iOS:在Info.plist中添加NSCameraUsageDescription、NSMicrophoneUsageDescription、NSPhotoLibraryUsageDescription的描述文本
  • 服务器端要支持接收multipart/form-data格式的文件上传

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:58:14