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

Ionic应用调用Cordova文件插件遇EACCES权限拒绝问题求助

嘿,这个权限拒绝的问题我太熟了!主要是Android 10及以上的存储机制变化,加上旧插件的适配问题导致的,我给你一步步解决:

问题根源

Android 10(API 29)引入了分区存储(Scoped Storage),限制了直接访问公共存储路径(比如/storage/emulated/0/Download/),而且cordova-plugin-file-transfer和cordova-plugin-file-chooser这类旧插件没完全适配这个变化,再加上权限申请不到位,就会抛出EACCES (Permission denied)。

解决步骤

1. 配置AndroidManifest.xml,兼容旧存储模式

首先在你的项目platforms/android/app/src/main/AndroidManifest.xml里做两个修改:

  • 在<application>标签添加requestLegacyExternalStorage,暂时绕过分区存储限制(过渡方案):
<application
  ...
  android:requestLegacyExternalStorage="true">
  • 添加必要的存储权限:
<!-- 适配Android 12及以下 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 适配Android 13+,读取文档类文件需要这个 -->
<uses-permission android:name="android.permission.READ_MEDIA_DOCUMENTS" />

2. 主动申请运行时权限

Android 6及以上需要动态申请权限,别指望Manifest配置了就自动生效。用cordova-plugin-android-permissions插件来处理:
先安装插件:

ionic cordova plugin add cordova-plugin-android-permissions
npm install @ionic-native/android-permissions

3. 正确处理FileChooser返回的Content URI

fileChooser.open()返回的是content://格式的URI,而旧版file-transfer插件没法直接处理这个,需要用cordova-plugin-file把它转换成真实的文件路径:

修改你的openFile()方法:

import { File } from '@ionic-native/file/ngx';
import { AndroidPermissions } from '@ionic-native/android-permissions/ngx';
import { FileTransfer, FileTransferObject, FileUploadOptions } from '@ionic-native/file-transfer/ngx';
import { FileChooser } from '@ionic-native/file-chooser/ngx';

// ...

constructor(
  private fileChooser: FileChooser,
  private transfer: FileTransfer,
  private file: File,
  private androidPermissions: AndroidPermissions
) {}

async openFile() {
  console.log("openFile");
  
  // 第一步:检查并申请存储权限
  const permissionStatus = await this.androidPermissions.checkPermission(
    this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE
  );
  
  if (!permissionStatus.hasPermission) {
    const requestResult = await this.androidPermissions.requestPermission(
      this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE
    );
    if (!requestResult.hasPermission) {
      console.log("用户拒绝了存储权限,无法继续");
      return;
    }
  }

  try {
    // 打开文件选择器
    const uri = await this.fileChooser.open();
    console.log("选择的文件URI:", uri);

    // 解析Content URI为FileEntry
    this.file.resolveLocalFileSystemURL(uri).then(fileEntry => {
      fileEntry.file(file => {
        console.log("文件详情:", file);
        
        // 配置上传选项
        const options: FileUploadOptions = {
          fileKey: 'file',
          fileName: file.name,
          mimeType: file.type,
          chunkedMode: false,
          // 这里可以添加其他请求头或参数
        };

        // 创建上传实例并执行上传
        const fileTransfer: FileTransferObject = this.transfer.create();
        fileTransfer.upload(
          fileEntry.nativeURL,
          '你的后端上传接口地址',
          options
        ).then(uploadResult => {
          console.log("上传成功!", uploadResult);
        }).catch(uploadError => {
          console.error("上传失败:", uploadError);
        });
      });
    }).catch(resolveError => {
      console.error("解析文件URI失败:", resolveError);
    });
  } catch (chooserError) {
    console.error("打开文件选择器失败:", chooserError);
  }
}

4. 长远方案:替换废弃的FileTransfer插件

官方已经标记cordova-plugin-file-transfer为废弃了,推荐用原生的fetch或axios来上传文件,这样更适配新的Android存储机制。比如用fetch实现上传:

async uploadWithFetch(uri: string) {
  try {
    // 从Content URI获取Blob
    const response = await fetch(uri);
    const blob = await response.blob();
    
    // 构建FormData
    const formData = new FormData();
    // 这里的文件名可以从之前的file对象里获取,或者自己处理
    formData.append('file', blob, 'uploaded-file.pdf');

    // 发起上传请求
    const uploadResponse = await fetch('你的后端上传接口地址', {
      method: 'POST',
      body: formData,
      // 如果需要自定义请求头可以在这里加
      headers: {
        // 'Authorization': 'Bearer token'
      }
    });

    const result = await uploadResponse.json();
    console.log("上传成功:", result);
  } catch (error) {
    console.error("上传失败:", error);
  }
}

这样修改后,应该就能解决权限拒绝的问题了。记得测试不同Android版本的设备,尤其是Android 10+和13+的机型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:20:48