更新记录

1.0.0(2026-03-30) 下载此版本

音频文件选择原生插件,支持 iOS、Android、鸿蒙三平台


平台兼容性

uni-app(4.0)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× × × × × 5.0 12 鸿蒙 3.0+
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

audio-file-picker-uts 使用说明

📖 目录

  1. 插件简介
  2. 功能特性
  3. 支持的音频格式
  4. 快速开始
  5. [API 文档](#api 文档)
  6. 使用示例
  7. 配置说明
  8. 注意事项
  9. 常见问题
  10. 更新日志

插件简介

audio-file-picker-uts 是一款基于 UTS (UniApp TypeScript) 开发的跨平台音频文件选择插件,支持 iOS、Android、鸿蒙 三大平台,同时兼容 uni-appuni-app X

插件提供统一的 Promise API,可帮助用户从设备本地选择音频文件并获取文件信息,方便后续上传操作。

适用场景

  • 🎤 语音消息上传
  • 🎵 音乐文件上传
  • 🎧 音频作品提交
  • 📝 录音文件选择

功能特性

  • UTS 开发:基于 TypeScript,类型安全
  • 三平台支持:iOS、Android、鸿蒙
  • 兼容 uni-app X:支持最新的 uni-app X 框架
  • Promise API:现代化的异步 API
  • 完整的类型定义:TypeScript 类型支持
  • 支持云打包:无需离线打包
  • 多种音频格式:MP3、WAV、M4A、FLAC 等
  • 自动文件处理:自动复制到临时目录
  • 临时文件清理:提供清理 API
  • 跨框架支持:Vue 3、uni-app X

支持的音频格式

格式 扩展名 iOS Android 鸿蒙
MP3 .mp3
AAC/M4A .m4a, .aac
WAV .wav
FLAC .flac
AIFF .aiff
WMA .wma
OGG .ogg
AMR .amr

文件大小限制:建议不超过 150MB


快速开始

步骤 1:安装插件

在 HBuilderX 中:

工具 → 插件安装 → 安装插件 → 搜索 "audio-file-picker-uts" → 安装

步骤 2:配置 manifest.json

manifest.jsonapp-plusmodules 中添加:

{
  "modules": {
    "audio-file-picker-uts": {}
  }
}

步骤 3:配置权限

iOS 权限配置

manifest.jsonapp-plusdistributeiosprivacyDescription 中添加:

{
  "ios": {
    "privacyDescription": {
      "NSDocumentsFolderUsageDescription": "需要访问文件以选择音频文件",
      "NSAppleMusicUsageDescription": "需要访问媒体库以选择音频文件"
    }
  }
}

Android 权限配置

manifest.jsonapp-plusdistributeandroidpermissions 中添加:

{
  "android": {
    "permissions": [
      "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
      "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
      "<uses-permission android:name=\"android.permission.READ_MEDIA_AUDIO\"/>"
    ]
  }
}

步骤 4:使用插件

import { pickAudio } from '@/uni_modules/audio-file-picker-uts'

// 选择音频文件
const result = await pickAudio()

if (result.success && result.data) {
  console.log('文件信息:', result.data)
  // 上传文件...
}

API 文档

pickAudio(options?)

选择音频文件。

类型定义

function pickAudio(options?: PickAudioOptions): Promise<PickAudioResult>

参数

  • options (PickAudioOptions, 可选):配置选项
    • maxFileSize (number, 可选):最大文件大小(字节),默认 150MB
    • allowedExtensions (string[], 可选):允许的扩展名列表

返回Promise<PickAudioResult>

PickAudioOptions 结构

interface PickAudioOptions {
  maxFileSize?: number;           // 最大文件大小(字节)
  allowedExtensions?: string[];   // 允许的扩展名列表
}

PickAudioResult 结构

interface PickAudioResult {
  success: boolean;      // 是否成功
  data?: {
    name: string;        // 文件名
    size: number;        // 文件大小(字节)
    path: string;        // 文件路径
    tempFilePath: string; // 临时文件路径(用于上传)
    extension: string;   // 文件扩展名
    originalURL?: string; // 原始文件 URL(仅 iOS)
  };
  message?: string;      // 错误信息
}

示例

// 基础用法
const result = await pickAudio()

// 带配置
const result = await pickAudio({
  maxFileSize: 100 * 1024 * 1024, // 100MB
  allowedExtensions: ['mp3', 'wav', 'm4a']
})

// 处理结果
if (result.success && result.data) {
  console.log('文件名:', result.data.name)
  console.log('文件大小:', result.data.size)
  console.log('文件路径:', result.data.path)
  console.log('文件格式:', result.data.extension)
} else {
  console.error('选择失败:', result.message)
}

错误处理

try {
  const result = await pickAudio()
  if (!result.success) {
    console.error('选择失败:', result.message)
  }
} catch (error) {
  console.error('异常:', (error as Error).message)
}

cleanTempFile(filePath)

清理临时文件。

类型定义

function cleanTempFile(filePath: string): Promise<CleanFileCallback>

参数

  • filePath (string):文件路径

返回Promise<CleanFileCallback>

CleanFileCallback 结构

interface CleanFileCallback {
  success: boolean;    // 是否成功
  message?: string;    // 结果信息
}

示例

// 基础用法
const result = await cleanTempFile('/path/to/temp/file')

if (result.success) {
  console.log('清理成功')
} else {
  console.error('清理失败:', result.message)
}

// 上传后清理
const audioResult = await pickAudio()
if (audioResult.success && audioResult.data) {
  // 上传文件
  await uni.uploadFile({
    url: '你的接口',
    filePath: audioResult.data.tempFilePath,
    name: 'audio'
  })

  // 清理临时文件
  await cleanTempFile(audioResult.data.path)
}

使用示例

示例 1:基础用法

import { pickAudio, cleanTempFile } from '@/uni_modules/audio-file-picker-uts'

async function selectAndUpload() {
  try {
    // 1. 选择音频文件
    const result = await pickAudio()

    if (!result.success || !result.data) {
      console.error('选择失败:', result.message)
      return
    }

    const file = result.data
    console.log('文件信息:', file)

    // 2. 上传文件
    const uploadRes = await uni.uploadFile({
      url: 'https://your-api.com/upload',
      filePath: file.tempFilePath,
      name: 'audio',
      formData: {
        fileName: file.name,
        fileSize: file.size
      }
    })

    console.log('上传结果:', uploadRes)

    // 3. 清理临时文件
    await cleanTempFile(file.path)

  } catch (error) {
    console.error('错误:', (error as Error).message)
  }
}

示例 2:Vue 3 组件中使用

<template>
  <view class="container">
    <button @click="selectAudio" class="btn-choose">
      🎤 选择音频文件
    </button>

    <view v-if="selectedFile" class="file-info">
      <text class="file-name">{{ selectedFile.name }}</text>
      <text class="file-size">{{ formatSize(selectedFile.size) }}</text>

      <button @click="uploadFile" class="btn-upload">
        ⬆️ 上传文件
      </button>
    </view>
  </view>
</template>

<script lang="ts">
import { ref } from 'vue'
import { pickAudio, cleanTempFile } from '@/uni_modules/audio-file-picker-uts'
import type { AudioFileInfo } from '@/uni_modules/audio-file-picker-uts'

export default {
  setup() {
    const selectedFile = ref<AudioFileInfo | null>(null)

    // 选择音频
    const selectAudio = async () => {
      try {
        const result = await pickAudio({
          maxFileSize: 150 * 1024 * 1024,
          allowedExtensions: ['mp3', 'wav', 'm4a']
        })

        if (result.success && result.data) {
          selectedFile.value = result.data
          uni.showToast({ title: '选择成功', icon: 'success' })
        } else {
          uni.showToast({ 
            title: result.message || '选择失败', 
            icon: 'none' 
          })
        }
      } catch (error) {
        uni.showToast({ 
          title: (error as Error).message, 
          icon: 'none' 
        })
      }
    }

    // 上传文件
    const uploadFile = async () => {
      if (!selectedFile.value) return

      try {
        await uni.uploadFile({
          url: 'https://your-api.com/upload',
          filePath: selectedFile.value.tempFilePath,
          name: 'audio',
          formData: {
            fileName: selectedFile.value.name,
            fileSize: selectedFile.value.size
          },
          success: () => {
            uni.showToast({ title: '上传成功', icon: 'success' })
            // 清理临时文件
            cleanTempFile(selectedFile.value!.path)
          },
          fail: (err) => {
            uni.showToast({ title: '上传失败', icon: 'none' })
          }
        })
      } catch (error) {
        uni.showToast({ title: '上传失败', icon: 'none' })
      }
    }

    // 格式化文件大小
    const formatSize = (bytes: number): string => {
      if (bytes < 1024) return bytes + ' B'
      if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB'
      return (bytes / (1024 * 1024)).toFixed(2) + ' MB'
    }

    return {
      selectedFile,
      selectAudio,
      uploadFile,
      formatSize
    }
  }
}
</script>

<style scoped>
.container {
  padding: 30rpx;
}

.btn-choose {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: #fff;
  border-radius: 44rpx;
}

.file-info {
  margin-top: 30rpx;
  padding: 30rpx;
  background: #f5f5f5;
  border-radius: 16rpx;
}

.btn-upload {
  margin-top: 20rpx;
  background: linear-gradient(135deg, #11998e, #38ef7d);
  color: #fff;
  border-radius: 44rpx;
}
</style>

示例 3:错误处理

import { pickAudio } from '@/uni_modules/audio-file-picker-uts'

async function selectAudioWithRetry(maxRetries = 3) {
  let lastError: Error | null = null

  for (let i = 0; i < maxRetries; i++) {
    try {
      const result = await pickAudio()

      if (result.success && result.data) {
        return result.data
      } else {
        console.warn(`尝试 ${i + 1} 失败:`, result.message)
        lastError = new Error(result.message)
      }
    } catch (error) {
      console.warn(`尝试 ${i + 1} 异常:`, (error as Error).message)
      lastError = error as Error
    }

    // 等待一段时间后重试
    if (i < maxRetries - 1) {
      await new Promise(resolve => setTimeout(resolve, 1000))
    }
  }

  throw lastError || new Error('选择音频失败')
}

示例 4:批量选择(多次调用)

import { pickAudio } from '@/uni_modules/audio-file-picker-uts'

async function selectMultipleAudioFiles(count: number) {
  const files: AudioFileInfo[] = []

  for (let i = 0; i < count; i++) {
    try {
      const result = await pickAudio()
      if (result.success && result.data) {
        files.push(result.data)
      }
    } catch (error) {
      console.error(`选择第 ${i + 1} 个文件失败:`, error)
      break
    }
  }

  return files
}

// 使用
const files = await selectMultipleAudioFiles(3)
console.log('选择的文件:', files)

配置说明

manifest.json 完整配置

{
  "app-plus": {
    "modules": {
      "audio-file-picker-uts": {}
    },
    "distribute": {
      "ios": {
        "devices": "universal",
        "deploymentTarget": "11.0",
        "privacyDescription": {
          "NSDocumentsFolderUsageDescription": "需要访问文件以选择音频文件",
          "NSAppleMusicUsageDescription": "需要访问媒体库以选择音频文件"
        },
        "LSSupportsOpeningFilesInPlace": true,
        "UISupportsDocumentBrowser": true
      },
      "android": {
        "permissions": [
          "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
          "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
          "<uses-permission android:name=\"android.permission.READ_MEDIA_AUDIO\"/>"
        ]
      }
    }
  }
}

版本要求

依赖 最低版本 说明
HBuilderX 3.99.0 UTS 语法支持
uni-app 4.0.0 UTS 运行时支持
uni-app X 1.0.0 完整支持
Vue 3.0 仅支持 Vue 3

平台支持

平台 支持状态 最低版本
iOS iOS 11.0+
Android Android 5.0+
鸿蒙 HarmonyOS 3.0+
H5 不支持
小程序 不支持

注意事项

1. 平台限制

  • 仅支持 App 端:iOS、Android、鸿蒙
  • 不支持 H5:H5 请使用 <input type="file">
  • 不支持小程序:小程序请使用 uni.chooseFile

2. Vue 版本限制

  • 支持 Vue 3
  • 不支持 Vue 2

3. 文件大小

  • 建议限制在 150MB 以内
  • 过大的文件可能导致内存问题或上传失败

4. 临时文件

  • 选择的文件会自动复制到临时目录
  • 上传后建议调用 cleanTempFile 清理
  • 临时文件在应用重启后可能会被系统清理

5. 权限申请

  • iOS:需要配置隐私描述
  • Android:需要存储权限(插件会自动申请)
  • 鸿蒙:无需特殊权限

6. 异步处理

  • 使用 async/awaitPromise.then() 处理结果
  • 建议添加错误处理逻辑

7. 真机测试

  • 必须使用真机模拟器测试
  • HBuilderX 预览模式不支持原生插件
  • 需要使用自定义基座云打包

常见问题

Q1: 插件不可用?

A:

  1. 确认已安装插件
  2. 确认 manifest.json 已配置模块
  3. 确认 HBuilderX 版本 >= 3.99.0
  4. 重启 HBuilderX
  5. 使用自定义基座或云打包

Q2: 提示"pickAudio is not a function"?

A:

// ❌ 错误导入
import pickAudio from '@/uni_modules/audio-file-picker-uts'

// ✅ 正确导入
import { pickAudio } from '@/uni_modules/audio-file-picker-uts'

Q3: 选择文件后没有返回?

A:

  1. 查看控制台日志
  2. 确认平台支持(仅 App 端支持)
  3. 检查权限配置
  4. 确认使用真机或模拟器

Q4: 上传失败?

A:

  1. 确认上传接口地址正确
  2. 检查网络权限
  3. 查看上传接口日志
  4. 确认使用 tempFilePath 上传

Q5: 如何在 H5 或小程序中使用?

A: UTS 插件是原生能力扩展,仅支持 App 端。

H5 替代方案

<template>
  <input type="file" @change="handleFileChange" accept="audio/*" />
</template>

小程序替代方案

uni.chooseFile({
  type: 'file',
  success: (res) => {
    console.log(res)
  }
})

Q6: 如何获取文件时长?

A: 插件目前只返回文件基本信息。如需获取音频时长,可以使用:

// iOS/Android 需要使用原生插件或 API
// 简单方案:使用 uni.createInnerAudioContext
const audio = uni.createInnerAudioContext()
audio.src = file.path
audio.onCanplay(() => {
  console.log('时长:', audio.duration)
  audio.destroy()
})

Q7: 支持批量选择吗?

A: 目前不支持一次选择多个文件。可以多次调用实现:

const files = []
for (let i = 0; i < 3; i++) {
  const result = await pickAudio()
  if (result.success && result.data) {
    files.push(result.data)
  }
}

更新日志

v1.0.0 (2024-01-01)

  • ✅ 初始版本发布
  • ✅ 基于 UTS 开发
  • ✅ 支持 iOS、Android、鸿蒙三平台
  • ✅ 兼容 uni-app 和 uni-app X
  • ✅ 完整的 TypeScript 类型支持
  • ✅ Promise 异步 API
  • ✅ 支持临时文件清理

🔗 相关资源

  • UTS 官方文档:https://uniapp.dcloud.net.cn/uts/
  • uni-app X 文档:https://uniapp.dcloud.net.cn/uni-app-x/
  • 插件市场:https://ext.dcloud.net.cn/plugin?id=xxxxx
  • TypeScript 文档:https://www.typescriptlang.org/
  • uni-app 文档:https://uniapp.dcloud.net.cn/

📞 技术支持

如有问题,请:

  1. 查看本使用说明
  2. 在 DCloud 论坛提问:https://ask.dcloud.net.cn/
  3. 在插件市场留言

祝使用愉快! 🎉

隐私、权限声明

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

iOS: 访问"文件"App 中的音频文件,访问 Apple Music 媒体库中的音频; Android: 读取外部存储中的音频文件,写入临时文件到外部存储,读取音频媒体文件; 鸿蒙: 暂无;

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

插件不采集任何数据。

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

许可协议

MIT协议

暂无用户评论。