更新记录

1.0.0(2024-11-20)

文件选择uts插件


平台兼容性

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

rl-select-files - 文件选择

一个简单易用的文件选择器插件,支持多种文件类型选择、多选、进度显示等功能。

✨ 特性

  • 支持多种文件类型(图片、视频、音频等)
  • 支持单选和多选
  • 支持文件选择进度显示
  • 支持自定义文件类型
  • 支持大文件处理
  • 文件自动缓存管理

🎯 兼容性

  • iOS 14.0+
  • Android 10+
  • HormanyOS 观望中

📦 安装

将插件导入到项目的 uni_modules 目录下。

📖 API 说明

SelectFilesType 文件类型

type SelectFilesType = 'any' | 'media' | 'image' | 'video' | 'audio' | 'custom'

SelectFilesOptions 请求参数

参数 类型 必填 说明
type SelectFilesType 文件类型: 'any'/'media'/'image'/'video'/'audio'/'custom'
allowedExtensions string 自定义文件扩展名(type为custom时有效),如:'pdf,doc,docx'
allowMultiple boolean 是否允许多选
proceed function 处理进度回调
success function 选择成功回调
fail function 选择失败回调
cancel function 取消选择回调

SelectFilesProgress 进度数据

字段 类型 说明
currentFileIndex number 当前处理的文件索引
totalFiles number 总文件数
currentFileName string 当前文件名
progress number 当前文件进度(0-1)
totalProgress number 总体进度(0-1)

SelectFilesResult 返回数据 - 成功

字段 类型 说明
name string 文件名
size number 文件大小(字节)
formattedSize string 格式化后的文件大小(如:1.5MB)
cachePath string 文件缓存路径

SelectFilesFail 返回数据 - 失败

字段 类型 说明
errMsg string 错误信息

selectFiles 请求文件选择

字段 类型 说明
options SelectFilesOptions 请求信息

🔨 使用方法

基础用法

import { selectFiles } from '@/uni_modules/rl-select-files'

// 选择视频文件
selectFiles({
    type: 'video',             // 文件类型
    allowedExtensions: '',     // 允许的扩展名(type为custom时使用)
    allowMultiple: true,       // 是否允许多选
    // 处理进度回调
    proceed: (progress) => {
        console.log(
            `处理文件: ${progress.currentFileName} ` +
            `(${progress.currentFileIndex}/${progress.totalFiles}) - ` +
            `${Math.floor(progress.totalProgress * 100)}%`
        )
    },
    // 选择成功回调
    success: (files) => {
        console.log('选择的文件:', files)
    },
    // 选择失败回调
    fail: (error) => {
        console.error('选择失败:', error.errMsg)
    },
    // 用户取消选择回调
    cancel: () => {
        console.log('用户取消选择')
    }
})

完整实例

<template>
    <view>
        <view class="button-container">
            <button @click="filePickTest">选择文件</button>
            <button @click="filePickClear">清除缓存</button>
        </view>

        <!-- 进度显示 -->
        <view v-if="progress" class="progress-container">
            <text class="progress-text">{{progress}}</text>
        </view>

        <!-- 文件列表 - 修改这部分 -->
        <scroll-view vertical>
            <view class="file-list">
                <text class="list-title" v-if="pickFiles.length > 0">已选择的文件:</text>
                <view v-for="(file, index) in pickFiles" :key="index" class="file-item">
                    <view class="file-info">
                        <text class="file-name">{{file.name}}</text>
                        <text class="file-size">大小:{{file.formattedSize}}</text>
                        <text class="file-path" v-if="file.cachePath">缓存路径:{{file.cachePath}}</text>
                    </view>
                </view>
            </view>
        </scroll-view>
    </view>
</template>

<script>
    import {
        SelectFilesOptions,
        SelectFilesFail,
        SelectFilesResult,
        selectFiles,
        clearCache,
    } from '@/uni_modules/rl-select-files'

    export default {
        data() {
            return {
                title: 'Hello',
                progress: '',
                pickFiles: [] as SelectFilesResult[]
            }
        },
        methods: {
            filePickTest() {
                this.progress = "" 
                this.pickFiles.splice(0, this.pickFiles.length)
                let options: SelectFilesOptions = {
                    type: 'video',
                    allowedExtensions: '',
                    allowMultiple: true,
                    proceed: (progress) => {
                        this.progress = `处理文件: ${progress.currentFileName} ` +
                            `(${progress.currentFileIndex}/${progress.totalFiles}) - ` +
                            `${Math.floor(progress.totalProgress * 100)}%`
                    },
                    success: (result) => {
                        if(result != null) {
                            let files = JSON.parseArray<SelectFilesResult>(result)
                            let totalSize = 0
                            if(files != null) {

                                files?.map(file => {
                                    totalSize += file.size
                                })
                                let totalSizeFormat = this.formatSize(totalSize)
                                this.progress = `文件处理完毕` +
                                    ` - 共${files?.length}个文件` +
                                    ` - 共${totalSizeFormat}`

                                this.pickFiles.push(...files)
                            }
                        }
                    },
                    fail: (error) => {
                        console.error('选择失败:', error.errMsg)
                        uni.showToast({
                            title: error.errMsg,
                            icon: 'none'
                        })
                    },
                    cancel: () => {
                        console.log('用户取消选择')
                    }
                }
                selectFiles(options)
            },

            filePickClear() {
                clearCache()
                this.progress = ""
                this.pickFiles.splice(0, this.pickFiles.length)
                uni.showToast({
                    title: '缓存已清理',
                    icon: 'success'
                })
            },

            formatSize(size : number) : string {
                const units = ['B', 'KB', 'MB', 'GB', 'TB']
                let index = 0
                let fileSize = size
                while (fileSize >= 1024 && index < units.length - 1) {
                    fileSize /= 1024
                    index++
                }
                return `${fileSize.toFixed(1)} ${units[index]}`
            }
        },

        beforeDestroy() {
            clearCache()
        }
    }
</script>

<style>
    .button-container {
        padding: 0 20px;
        margin-bottom: 20px;
    }

    .button-container button {
        margin-bottom: 10px;
    }

    .progress-container {
        padding: 10px 20px;
        background-color: #f8f8f8;
        margin: 0 20px 20px 20px;
        border-radius: 5px;
    }

    .progress-text {
        font-size: 14px;
        color: #666;
    }

    /* 修改文件列表样式 */
    .file-list {
        padding: 0 20px;
        flex: 1;
    }

    .list-title {
        font-size: 16px;
        font-weight: bold;
        margin-bottom: 10px;
        color: #333;
    }

    .file-item {
        background-color: #f8f8f8;
        padding: 15px;
        margin-bottom: 10px;
        border-radius: 8px;
    }

    .file-info {
        display: flex;
        flex-direction: column;
    }

    .file-name {
        font-size: 16px;
        font-weight: bold;
        color: #333;
        margin-bottom: 5px;
    }

    .file-size {
        font-size: 14px;
        color: #666;
        margin-bottom: 5px;
    }

    .file-path {
        font-size: 12px;
        color: #999;
        word-break: break-all;
    }
</style>

⚠️ 注意事项

  1. 选择的文件会自动缓存到本地,提高文件可操作性
  2. 建议在适当的时候调用 clearCache() 清理缓存
  3. 大文件处理时会显示进度
  4. iOS 14.0+ 设备才能使用此插件
  5. Android 10+ 设备才能使用此插件
  6. 在组件销毁时记得调用 clearCache() 清理缓存
  7. 大文件(>10MB)会自动使用分块处理以提高性能
  8. 文件选择完成后会返回缓存路径,可以直接使用
  9. 支持安全的文件访问机制
  10. 选择取消时会触发 cancel 回调
  11. 支持可达1G以上大文件

🤝 贡献/咨询

欢迎提交 issue 和 PR,一起完善这个插件。 扣扣群:838332280

📝 开发文档

UTS 语法 UTS API插件 UTS 组件插件 Hello UTS

隐私、权限声明

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

Android: READ_EXTERNAL_STORAGE :读取存储权限 WRITE_EXTERNAL_STORAGE:写入存储权限 IOS: NSPhotoLibraryUsageDescription:是否允许App访问您的相册 NSPhotoLibraryAddUsageDescription:是否允许App访问您的相册 NSAppleMusicUsageDescription:是否允许App访问您的媒体资料库

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

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

暂无用户评论。

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