使用Media Capture Cordova插件录制/选视频并上传远程服务器遇异常
解决Cordova视频预览与上传的问题
我来帮你搞定这个头疼的问题!从你的代码来看,核心问题出在Cordova本地文件路径的处理以及视频文件的上传方式上,咱们一步步拆解解决:
一、先搞定视频预览的问题
你当前用的是MediaFile的fullPath属性,但这个路径在不同平台(iOS/Android)的格式并不统一,而且直接绑定到video标签会因为安全策略或者路径格式问题被拦截。
修复步骤:
改用
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)) }); }调整HTML的video标签绑定
因为已经提前处理了安全信任,直接绑定数组元素即可:<div *ngIf="dispVideos?.length > 0"> <video #myVideo preload="metadata" controls> <source [src]="dispVideos[0]" type="video/mp4"> </video> </div>检查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的描述文本
- Android:在
- 服务器端要支持接收
multipart/form-data格式的文件上传
内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

