首页 > 其他分享 >uniapp 文件管理器(文件选择)

uniapp 文件管理器(文件选择)

时间:2024-05-18 15:54:30浏览次数:17  
标签:文件 const uniapp Uri plus 管理器 android main id

  • 仅 app
// #ifdef APP-PLUS
export function openFileManager() {
  return new Promise(async (resolve, reject) => {
    try {
      await requestPermission();

      // 获取应用主Activity实例对象
      const main = plus.android.runtimeMainActivity();
      // console.log(main);
      // 导入Intent类
      const Intent = plus.android.importClass('android.content.Intent');
      // Intent.ACTION_PICK 图片
      // Intent.ACTION_GET_CONTENT 文件 (旧) 用于一次性获取文件的URI,适合于不需要频繁访问文件的场景
      // Intent.ACTION_OPEN_DOCUMENT 文件 提供了对文件的长期访问权限,更适合于需要频繁操作文件的应用场景
      const intent = new Intent(Intent.ACTION_GET_CONTENT);

      intent.addCategory(Intent.CATEGORY_OPENABLE);
      // 设置文件类型为任意类型
      intent.setType('*/*');
      // 多选
      intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

      const REQUEST_CODE = 1;

      main.onActivityResult = (requestCode, code, data) => {
        // 导入Activity类。
        const Activity = plus.android.importClass('android.app.Activity');
        plus.android.importClass('android.net.Uri');
        // console.log(requestCode, code, Activity.RESULT_OK);

        // 选择的文件的路径
        let filePathList = [];

        // 选择文件
        if (code === Activity.RESULT_OK && requestCode === REQUEST_CODE) {
          // 导入Uri类。
          let Uri = data.getData();

          if (!Uri) {
            let ClipData = plus.android.importClass('android.content.ClipData');
            let clipData = new ClipData();
            clipData = data.getClipData();

            if (clipData) {
              // 返回选择的文件数量。
              const count = clipData.getItemCount();
              for (let i = 0; i < count; i++) {
                const item = clipData.getItemAt(i);
                const uri = item.getUri();
                const filePath = getFilePath(main, uri);
                filePathList.push(filePath);
              }
            }
          } else {
            filePathList.push(getFilePath(main, Uri));
          }
        }

        resolve(filePathList);

        // if (!filePath.startsWith('file://')) {
        //   filePath = 'file://' + filePath;
        // }
        // console.log('filePath => ', filePath);

        // 获取文件信息,包括文件大小、文件类型等。
        // uni.getFileInfo({
        //   filePath,
        //   success: (res) => {
        //     console.log(res);
        //   },
        //   fail: (err) => console.log(err),
        // });
      };

      // 第一个参数是 Intent对象,用于指定要启动的Activity;
      // 第二个参数是 请求码(requestCode),用于标识请求来源
      main.startActivityForResult(intent, REQUEST_CODE); // 启动一个新的Activity并等待其返回结果
      // main.startActivityForResult(Intent.createChooser(intent, 'Select Picture'), 1);
    } catch (e) {
      reject(e);
    }
  });
}

/**
 * 获取文件路径
 * @param {Object} main 应用主Activity实例对象
 * @param {Object} Uri 文件路径对象
 */
function getFilePath(main, Uri) {
  const Build = plus.android.importClass('android.os.Build');
  const DocumentsContract = plus.android.importClass('android.provider.DocumentsContract');
  // 是否为文档类型的 URI
  const IS_DOUMENT_TYPE = DocumentsContract.isDocumentUri(main, Uri);
  const scheme = Uri.getScheme();
  // console.log(IS_DOUMENT_TYPE, scheme);

  // Build.VERSION.SDK_INT: 当前设备上运行的Android操作系统的API级别
  // Build.VERSION_CODES.KITKAT: Android 4.4(KitKat)版本的API级别
  // 判断安卓版本是否大于等于4.4(KitKat)
  // console.log(Build.VERSION.SDK_INT, Build.VERSION_CODES.KITKAT);
  const IS_KITKAT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  // console.log(IS_KITKAT);

  // 设备至少为4.4以上的版本,可以安全地使用某些API
  if (IS_KITKAT) {
    if (IS_DOUMENT_TYPE) {
      // 从 Uri 中提取出文件的 ID
      const docId = DocumentsContract.getDocumentId(Uri);
      const [type, id] = docId.split(':');

      // 获取指定URI的权限部分
      const authority = Uri.getAuthority();
      // console.log(authority, type, id, docId);

      const AUTHORITY_DOCUMENT_TYPE = {
        MEDIA: 'com.android.providers.media.documents',
        DOWNLOAD: 'com.android.providers.downloads.documents',
        EXTERNAL: 'com.android.externalstorage.documents',
      };

      const authorityFn = {
        [AUTHORITY_DOCUMENT_TYPE.DOWNLOAD]: getDownloadDocument,
        [AUTHORITY_DOCUMENT_TYPE.MEDIA]: getMediaDocument,
        [AUTHORITY_DOCUMENT_TYPE.EXTERNAL]: getExternalDocument,
      };
      return authorityFn[authority]?.({ main, Uri, docId, type, id });
    } else if (scheme === 'content') {
      // const authority = Uri.getAuthority();
      // console.log(authority);
      return getDataColumn(main, Uri);
    } else if (scheme === 'file') {
      return Uri.getPath();
    }
  } else {
    // 4.4以下
    const MediaStore = plus.android.importClass('android.provider.MediaStore');
    const columns = [MediaStore.Images.Media.DATA];
    const cursor = contentResolver.query(Uri, columns, null, null, null);
    if (cursor !== null && cursor.moveToFirst()) {
      const column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
      const filePath = cursor.getString(column_index);
      cursor.close();
      return filePath;
    }
  }
}

/**
 * @typedef AuthorityDocumentType 文档类型枚举对象
 * @property {Object} main
 * @property {Object} Uri 文件路径对象
 * @property {String} docId 文件的 ID
 * @property {String} type 文件类型,例如 'image'、'video'、'audio'等
 * @property {String} id id
 */

/**
 * 获取文件路径
 * @param {AuthorityDocumentType} options
 */
function getExternalDocument(options) {
  const { type, id } = options;
  const Environment = plus.android.importClass('android.os.Environment');

  let path = '';
  if (type === 'primary') {
    // 获取外部存储目录的绝对路径。
    path = `${Environment.getExternalStorageDirectory()}/${id}`;
  } else {
    const System = plus.android.importClass('java.lang.System');
    path = `${System.getenv('SECONDARY_STORAGE')}/${id}`;
  }
  return path;
}
/**
 * 获取文件路径
 * @param {AuthorityDocumentType} options
 */
function getMediaDocument(options) {
  const { main, id, type } = options;
  const MediaStore = plus.android.importClass('android.provider.MediaStore');
  const MEDIA_TYPE = {
    image: MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    video: MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
    audio: MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
    document: MediaStore.Files.getContentUri('external'),
  };

  const uri = MEDIA_TYPE[type] || null;
  return getDataColumn(main, uri, '_id=?', [id]);
}
/**
 * 获取文件路径
 * @param {AuthorityDocumentType} options
 */
function getDownloadDocument(options) {
  const { main, Uri, id } = options;

  if (id) {
    return id;
  }

  const ContentUris = plus.android.importClass('android.content.ContentUris');
  // 第一个参数 原始的 content URI
  // 第二个参数 要附加的 ID
  // 返回一个新 URI,其中 ID 已附加到原始 URI。
  const originId = Uri.parse('content://downloads/public_downloads');
  const newId = ContentUris.parseId(Uri);
  const uri = ContentUris.withAppendedId(originId, newId);
  return getDataColumn(main, uri);
}

/**
 * uri路径转换
 * @param {Object} context 应用主Activity实例对象
 * @param {Object} uri 文件路径
 * @param {String} selection
 * @param {Array} selectionArgs  文件的id数组
 */
function getDataColumn(context, uri, selection = null, selectionArgs = null) {
  // 导入Uri类。
  plus.android.importClass(context.getContentResolver());

  const _columns = ['_data']; // 指定要查询的列。
  // 查询指定URI的路径。
  const Cursor = context.getContentResolver().query(uri, _columns, selection, selectionArgs, null);

  // 导入Cursor类。
  Cursor && plus.android.importClass(Cursor);

  let filePath = '';
  // 检查游标是否为空 且 移动到第一行数据。
  if (Cursor !== null && Cursor.moveToFirst()) {
    // 获取指定列的索引。
    const columnIndex = Cursor.getColumnIndexOrThrow(_columns[0]);
    // 文件路径
    filePath = Cursor.getString(columnIndex);
    // 关闭游标。
    Cursor.close();
  }
  return filePath;
}

const PERMISSION_TYPE = {
  // 允许
  PERMISSION_GRANTED: 0,
  // 临时拒绝
  PERMISSION_DENIED: 1,
  // 永久拒绝
  PERMISSION_DENIED_FOREVER: 2,
};

// 申请权限
function requestPermission() {
  return new Promise((resolve, reject) => {
    plus.android.requestPermissions(
      ['android.permission.READ_EXTERNAL_STORAGE'],
      (e) => {
        if (e.deniedAlways.length > 0) {
          // 权限被永久拒绝
          // 弹出提示框解释为何需要存储权限,引导用户打开设置页面开启
          // console.log('Always Denied!!! ' + e.deniedAlways.toString());
          reject({
            code: PERMISSION_TYPE.PERMISSION_DENIED_FOREVER,
            msg: '未授权且不再询问',
          });
        }
        if (e.deniedPresent.length > 0) {
          // 权限被临时拒绝
          // 弹出提示框解释为何需要存储权限,可再次调用plus.android.requestPermissions申请权限
          // console.log('Present Denied!!! ' + e.deniedPresent.toString());
          // plus.android.requestPermissions(['android.permission.READ_EXTERNAL_STORAGE']);
          reject({
            code: PERMISSION_TYPE.PERMISSION_DENIED,
            msg: '未授权',
          });
        }
        if (e.granted.length > 0) {
          // 权限被允许
          // 调用依赖获取存储权限的代码
          // console.log('Granted!!! ' + e.granted.toString());
          resolve({
            code: PERMISSION_TYPE.PERMISSION_GRANTED,
            msg: '已授权',
          });
        }
      },
      (e) => {
        // console.log('Request Permissions error:' + JSON.stringify(e));
        reject(e);
      }
    );
  });
}
// #endif

标签:文件,const,uniapp,Uri,plus,管理器,android,main,id
From: https://www.cnblogs.com/chlai/p/18199386

相关文章

  • 基于uniapp+vue3自定义增强版table表格组件「兼容H5+小程序+App端」
    vue3+uniapp多端自定义table组件|uniapp加强版综合表格组件uv3-table:一款基于uniapp+vue3跨端自定义手机端增强版表格组件。支持固定表头/列、边框、斑马纹、单选/多选,自定义表头/表体插槽、左右固定列阴影高亮显示。支持编译兼容H5+小程序端+App端。如下图:H5+小程序+App端,多端......
  • 如何把多个文件(夹)向下移动1层(在复制前或后进行)
    首先,需要用到的这个工具:度娘网盘提取码:qwu2蓝奏云提取码:2r1z 先看一下文件夹的结构,一共4个文件夹,1-4编号,每个里面都有兔兔的图片,作为操作说明(实际就按自己要处理的文件)打开工具,切换到“文件批量复制”的版块思路:先把4个文件夹拖入到“来源路径”里,整理一下,去掉......
  • 如何从多个文件夹内转移全部文件(忽略文件夹的结构)(进行复制)(再打包)
    首先,需要用到的这个工具:度娘网盘提取码:qwu2蓝奏云提取码:2r1z 04文件夹里面有只有1个名称为"1"的文件夹,“1”里面有“2”,“2”有“3”,“3”有“4”,从“1”开始,都有5个兔兔的图片,这是“1”里面的文件夹结构,现在要做的就是忽略文件夹结构,提取出全部的兔兔图片合并成一个压缩......
  • 一次nginx文件打开数的问题排查处理
     现象:nginx域名配置合并之后,发现consul-template无法完成nginx重载,然后发现需要重启nginx,才能让配置生效。注意:下次哪个服务有报错,就看重启时所有日志输出,各种情况日志输出。不要忽略细节。很多时候其实已经看到了问题,却没有深入查看问题。  查看进程最大打开文件个数#ca......
  • 【Delphi 开箱即用 1】简单实现拖拽文件到窗口
    当今,大多数个人小程序都普遍具备拖拽功能,因为拖拽操作极其便捷。毕竟,相比于传统的浏览文件夹方式打开目标文件,拖拽操作简直是一种解放。在这里,我们无需依赖任何第三方控件,单纯通过代码实现拖拽功能。目录1.最终效果图2.部分核心代码3.完整Demo源码下载1.最终效果图2.部分......
  • Oracle移动文件
    关闭数据库SQL>shutdownimmediateDatabaseclosed.Databasedismounted.ORACLEinstanceshutdown.移动数据文件,用oracle用户操作[oracle@test~]$mv/u01/app/oracle/oradata/ORCL/system01.dbf/home/oracle/oradata/system01.dbf[oracle@test~]$mv/u01/app/oracl......
  • iOS获取.ips文件并通过Xcode自带的symbolicatecrash解析
    文章讲述如下问题:1.如何获取.ips文件2.如何获取symbolicatecrash3.解析前的准备工作4.如何将.ips转为.crash文件5.如何使用symbolicatecrash解析.crash文件6.异常错误处理1.如何获取.ips文件?在iOS中,你可以通过几种方式找到应用程序的.ips文件,具体取决于你是在开发......
  • 七牛云文件批量上传加单个上传和下载
    第一步:先在七牛云官网注册一个账号然后点击对象存储-空间管理-新建空间创建一个存储空间创建好之后就完成了第一步可以往里面放东西了第二步:打开你的VS创建一个类改成静态类方便外部调用写一个静态的方法///<summary>///上传文件类///</summary>public......
  • C++读取配置文件
    1、读取=号的配置文件(或者:)的配置。#include<iostream>#include<fstream>#include<sstream>#include<map>#include<string>std::map<std::string,std::string>read_config(conststd::string&filename){std::map<std::st......
  • 手机怎么把pdf文件转成excel表格
    在大数据的时代,用数据来指导分析已越来越普遍。有时候希望使用pdf文件中的表格数据,但是pdf文件无法直接编辑,复制和粘贴是很麻烦的。尤其是当分析一些数据时,需要将pdf转excel表格,那么你知道手机怎么实现pdf文件转excel表格吗?使用在线转换工具是最简单、最快捷的方式之一。它不仅不......