Ionic上传视频时遭遇EACCES(权限拒绝)错误求助
我之前也碰到过几乎一模一样的问题,结合你的代码和错误日志来看,核心原因是Android 10及以上版本的分区存储(Scoped Storage)限制,再加上插件的适配问题,具体分析和解决方法如下:
问题根源
- 分区存储的限制:从Android 10(API 29)开始,系统默认启用分区存储机制,就算你申请了
READ_EXTERNAL_STORAGE权限,直接通过file://路径访问公共目录(比如DCIM/Camera)下的视频文件也会被拒绝。而图片能正常工作,是因为Camera插件或系统兼容层对图片做了特殊处理,绕过了部分限制。 - 插件的文件访问逻辑:
cordova-plugin-advanced-http在处理file://路径时,是直接用原生文件IO去打开文件的,这种方式在分区存储规则下不被允许,所以触发了权限拒绝错误。
解决方法
方法一:临时绕过分区存储(快速见效)
这是最快解决问题的方案,适合快速验证或临时版本:
在你的Android项目AndroidManifest.xml的<application>标签中添加requestLegacyExternalStorage属性,让应用暂时使用旧的文件访问模式:
<application ... android:requestLegacyExternalStorage="true">
⚠️ 注意:这只是临时方案,Android 11及以上版本对该属性的支持正在收紧,长期来看还是要适配分区存储。
方法二:适配分区存储(推荐长期方案)
1. 修改Camera插件的返回类型
把destinationType从FILE_URI改成NATIVE_URI,这样插件会返回Content URI(比如content://media/external/video/media/123)而非直接的文件路径,这是符合分区存储规则的访问方式:
const options: CameraOptions = { destinationType: this.camera.DestinationType.NATIVE_URI, // 替换为NATIVE_URI mediaType: this.camera.MediaType.ALLMEDIA, sourceType: SOURCE };
2. 确保Advanced HTTP插件支持Content URI上传
升级cordova-plugin-advanced-http到最新版本,最新版已经支持Content URI的上传,直接传入返回的Content URI即可:
cordova plugin update cordova-plugin-advanced-http
3. 可选:用File插件转换路径(兼容旧版插件)
如果你的Advanced HTTP版本较低无法支持Content URI,可以用cordova-plugin-file把Content URI转成可访问的文件对象:
import { File } from '@ionic-native/file/ngx'; // 在startUpload方法中替换原有逻辑 this.file.resolveLocalFilesystemUrl(fileUrl).then(fileEntry => { fileEntry.file(file => { this.nativeHttp.uploadFile(req.url, null, headers, fileEntry.nativeURL, fileName) .then(res => { /* 处理上传结果 */ }) .catch(err => { /* 处理错误 */ }); }); });
方法三:特殊场景下的权限申请(不推荐)
如果你的应用是文件管理器这类需要全文件访问的场景,可以申请MANAGE_EXTERNAL_STORAGE权限,但这个权限需要用户手动在应用设置中开启,且Google Play会严格审核这类权限的使用,非必要不建议采用。
按照上面的方法修改后,重新编译应用测试,应该就能解决视频上传的EACCES错误了。
内容的提问来源于stack exchange,提问作者brevleq

