更新记录

1.0.10(2024-08-16)

  1. 修复高版本Android系统个别机型的适配问题

1.0.9(2024-03-27)

  1. Android补充系统文件选择器的支持

1.0.8(2024-01-09)

  1. 适配Android 10以后读取U盘文件方案
查看更多

平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 3.6.8,Android:4.4,iOS:9,HarmonyOS:不确定 × × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序
× × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

读写外接U盘、移动硬盘、SD卡、缓存目录、数据目录、自定义目录等文件

常用文件处理插件

  1. 文件预览https://ext.dcloud.net.cn/plugin?id=17167

    • 支持pdf/word/excel/ppt/图片,支持本地或在线文件
  2. 文件增删查改copy遍历https://ext.dcloud.net.cn/plugin?id=14130

    • 文件读写、copy、move、遍历文件夹、是否存在、删除、重命名......等等
  3. 读取常用文件目录(包含U盘)https://ext.dcloud.net.cn/plugin?id=15243

    • uniapp(_www、_doc、_download)
    • Android(数据目录、文件目录、缓存目录、环境environment目录、SDCard目录、外接U盘)
    • iOS(documentDirectory、temporaryDirectory、libraryDirectory、cachesDirectory)
    • 从U盘读取或保存文件
  4. 读取本地相册图片视频音频https://ext.dcloud.net.cn/plugin?id=15711

    • 获取相册图片、视频、音频文件
    • 常用于自定义相册UI

读取U盘文件

  • android通过getStorageVolumes接口直接获取到U盘路径,通过UTSFileUtils来遍历U盘路径下的所有文件
  • ios受限系统没法直接读取到U盘路径,可以通过selectFile来拉起文件app,把用户选择到文件保存到自定义目录,通过UTSFileUtils来读取文件
  • android 10需要采用系统文件选择器来获取或保存
  • Android 11以后需要手动打开授予管理所有文件的权限,路径: 设置-》隐私与安全(或隐私保护) -》其他权限-》特殊权限设置-》所有文件访问权限-》选择app-》进入授权页面授权(授予管理所有文件的权限),开启权限后重启app,再进行usb授权后,进入u盘目录即可

写入文件到U盘

  • android需要先获取USB文件授权(通过UTSUsbManager插件来请求USB权限),通过getStorageVolumes接口直接获取到U盘路径,通过UTSFileUtils将文件写入到U盘
  • ios受限系统没法直接保存文件到U盘,可以通过saveFile来保存文件

获取app开发中常用到目录路径

  • uniapp(_www、_doc、_download)
  • Android(数据目录、文件目录、缓存目录、环境environment目录、SDCard目录)
  • iOS(documentDirectory、temporaryDirectory、libraryDirectory、cachesDirectory)

demo里用到了文件插件(android和iOS对文件增删查改)https://ext.dcloud.net.cn/plugin?id=14130,即:


    import {
        UTSFileUtils
    } from "@/uni_modules/wrs-uts-commonutils"

demo里用到了USB权限插件(android对USB授权,iOS不需要)https://ext.dcloud.net.cn/plugin?id=13300,即:


    import {
    UTSUsbManager,
} from "@/uni_modules/wrs-uts-usbmanager";

如果需要监听Android U盘的插拔和USB权限操作,可以使用这个插件https://ext.dcloud.net.cn/plugin?id=13300

如果需要写入数据到U盘,需要先请求USB权限


    UTSUsbManager.getDeviceList((resp) => {
    let devices = resp.devices;
    if (devices.length > 0) {
        let titles = [];
        for (let i = 0; i < devices.length; i++) {
            let device = devices[i];
            let title = device.deviceName;
            titles.push(title);
        }
        this.showActionSheet(titles, (index) => {
            let device = devices[index];
            let deviceId = device.deviceId;
            let requestCode = this.requestCode;
            let action = this.action;
            let flags = 0;

            UTSUsbManager.requestPermission(deviceId, requestCode, action, flags);
        });
    } else {
        this.showToast("没有找到USB设备");
    }
});

不熟悉UTS插件集成步骤的同学可以参数https://www.jianshu.com/p/830ccc503e29

Android配置

  1. 下载示例项目demo,将demo里的AndroidManifest.xml和nativeResources拷贝到自己项目的根目录,如果已经存在对应文件,请合并里面的内容(如果不会合并加QQ252797991)
  2. 将AndroidManifest.xml文件的manifest节点的package值设置Android打包的包名
  3. 增加权限

   "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
    "<uses-permission android:name=\"android.permission.MANAGE_EXTERNAL_STORAGE\"/>"
  • 关于Android 10、11及其以后系统无法访问外接U盘,没有读写权限的方案
  1. android 10需要采用系统文件选择器来选取和保存文件到U盘

UTSFilePath.selectFile()
UTSFilePath.saveFile()

var sdkVersion = UTSFilePath.getSDKVersion()
if(sdkVersion == 29) { // android 10系统

}
  1. android 11以后需要跳到文件设置页面进行授权,授权以后重启app才能对外部路径(如U盘)进行读写。 路径:设置-》隐私与安全(或隐私保护) -》其他权限-》特殊权限设置-》所有文件访问权限-》选择app-》进入授权页面授权(授予管理所有文件的权限),开启权限后重启app,再进行usb授权后,进入u盘目录即可

var sdkVersion = UTSFilePath.getSDKVersion()
if (sdkVersion >= 30) { // android 11以后需要跳到文件设置页面进行授权,授权以后重启app才能访问外部路径
    var isExternalStorageManager = UTSFilePath.isExternalStorageManager()
    if(!isExternalStorageManager) {
        UTSFilePath.toMgrAllFilesPermissionPage()
    }
}

引入插件


    import {
        UTSFilePath
    } from "@/uni_modules/wrs-uts-filePath"
  • 获取手机所有存储卷路径,包含外接U盘、移动硬盘,仅支持Android

    var resp = UTSFilePath.getStorageVolumes()
                    if (resp.storageVolumes) {
                        this.dataArray.push(...resp.storageVolumes)
                    }

返回的数据结构:


{
    "storageVolumes": [{
        "isRemovable": false, // 是否可插拔,true表示是外接的U盘或移动硬盘,false表示是内部固定盘
        "description": "内部存储",
        "state": "mounted",
        "path": "/storage/emulated/0"
    }, {
        "isRemovable": true, // true表示是外接的U盘或移动硬盘
        "description": "U 盘",
        "state": "mounted",
        "path": "/storage/C0C4-9B54"
    }]
}
  • 获取app常用路径

var commonPath = UTSFilePath.getCommonPath()

返回的数据结构:

android:


{
    "environment": {
        "downloadCacheDirectory": "/data/cache", 
        "dataDirectory": "/data",
        "externalStorageDirectory": "/storage/emulated/0",
        "rootDirectory": "/system",
        "externalStorageState": "mounted"
    },
    "cacheDir": "/data/user/0/uni.UNI005DB01/cache",
    "externalCacheDir": "/storage/emulated/0/Android/data/uni.UNI005DB01/cache",
    "dataDir": "/data/user/0/uni.UNI005DB01",
    "filesDir": "/data/user/0/uni.UNI005DB01/files"
}

ios: 常用的路径有:documentDirectory、temporaryDirectory、libraryDirectory、cachesDirectory


{
    "desktopDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Desktop",
    "homeDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB",
    "allApplicationsDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Applications",
    "adminApplicationDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Applications/Utilities",
    "preferencePanesDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library/PreferencePanes",
    "applicationSupportDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library/Application Support",
    "temporaryDirectory": "/private/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/tmp/",
    "documentationDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library/Documentation",
    "moviesDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Movies",
    "developerDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Developer",
    "developerApplicationDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Developer/Applications",
    "documentDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Documents",
    "inputMethodsDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library/Input Methods",
    "cachesDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library/Caches",
    "musicDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Music",
    "picturesDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Pictures",
    "allLibrariesDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library",
    "sharedPublicDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Public",
    "autosavedInformationDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library/Autosave Information",
    "libraryDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Library",
    "demoApplicationDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Applications/Demos",
    "applicationDirectory": "/var/mobile/Containers/Data/Application/4B6CBD9F-2B8B-4110-B9F1-698509C213BB/Applications"
}
  • 调用系统文件选择器来选择文件(从U盘或移动硬盘里获取文件)

ar params = {}
if (this.isAndroid) { // ios
    // image/*、audio/*、video/*、video/*;image/*
    params.type = "*/*" //无类型限制
    params.category = ["android.intent.category.OPENABLE"]
    // params.extra = {
    //  'android.intent.extra.ALLOW_MULTIPLE': true // 是否允许多选
    // }

} else {
    params.modalPresentationStyle = 0
    params.documentTypes = [
        "public.item",
        "public.data",
        "public.symlink",
        "public.directory",
        "public.content",
        "public.text",
        "public.source-code",
        "public.image",
        "public.audiovisual-content",
        "com.adobe.pdf",
        "com.apple.keynote.key",
        "com.microsoft.word.doc",
        "com.microsoft.excel.xls",
        "com.microsoft.powerpoint.ppt",
        "org.openxmlformats.wordprocessingml.document",
        "com.microsoft.excel.xls",
        "org.openxmlformats.presentationml.presentation"
    ] // 可以选择的文件类型,更多类型请查询资料自行添加
    params.allowsMultipleSelection = true // 是否允许多选,ios 11以后支持
    params.modalPresentationStyle = 0
}
params.saveDir = plus.io.convertLocalFileSystemURL("_download") // 文件保存目录
UTSFilePath.selectFile(JSON.stringify(params), (resp) => {
    // android与iOS返回到resp值不一样,需要各端去适配
    this.showMsg(JSON.stringify(resp))
    var opt = resp.opt
    switch (opt) {
        case "presented":

            break
        case "cancel":
            break;
            // 选择完文件开始保存文件
        case "didPick":

            break
            // 文件保存完成
        case "savedFiles":
            break
        default:
            break;
    }
})
  • 调用文件选择器来保存文件(可以保存文件到U盘或移动硬盘里)

                var params = {};
params.url = plus.io.convertLocalFileSystemURL("_www/static/logo.png");
if (this.isAndroid) { 
    params.EXTRA_TITLE = "logo.png"

} else {
    params.allowsMultipleSelection = false // 是否允许多选,ios 11以后支持
    params.modalPresentationStyle = 0
}

UTSFilePath.saveFile(JSON.stringify(params), (resp) => {
    // android与iOS返回到resp值不一样,需要各端去适配
    this.showMsg(JSON.stringify(resp))
    if (this.isAndroid) {
        var resultCode = resp.resultCode
        if (resultCode == -1) {
            let fileArray = resp.fileArray
            if (fileArray) {

            }
        }
    } else {
        var opt = resp.opt
        switch (opt) {
            case "presented":

                break
            case "cancel":
                break;
            case "didPick":

                break
            case "savedFiles":
                break
            default:
                break;
        }
    }

})

如果觉得可以就点个👍吧,欢迎粉丝收藏,土豪打赏,您的关注就是我们创作的动力!

隐私、权限声明

1. 本插件需要申请的系统权限列表:

读写权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问