更新记录

1.0.0(2026-09-08) 下载此版本

  • 首个版本:Android / iOS / HarmonyOS 三端网络文件下载,落盘系统公共目录
  • Android:Android 10+ 走 MediaStore(免权限静默保存),Android 9- 直接写公共 Download(自动申请权限)
  • iOS:保存到 Documents,配合 UIFileSharingEnabled 在「文件」App 可见
  • HarmonyOS:FilePicker DOWNLOAD 模式(API 12+)静默授权 Download/<包名> 目录
  • 提供 downloadToPublic(下载+落盘)与 saveFileToPublic(本地文件转存)两个 API

平台兼容性

uni-app(3.8.3)

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

uni-app x(3.8.3)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

lv-downloader 三端文件下载(保存到公共目录)

下载网络文件(URL)并保存到系统公共目录,支持 Android / iOS / HarmonyOS 三端。文件不落隐藏目录、不落应用沙盒缓存。

三端保存位置

平台 保存位置 用户如何看到 是否弹窗 权限
Android /storage/emulated/0/Download/<subDir>/ 文件管理 → 下载 否(静默) Android 10+ 免权限;Android 9- 自动申请存储权限
iOS 应用 Documents/<subDir>/ 保存成功后自动弹系统分享面板,选「存储到文件」可存到任意位置 保存后弹系统面板
HarmonyOS Download/<应用包名>/ 文件管理 → 浏览 → 下载 否(DOWNLOAD 模式静默授权)

iOS 系统没有全局公共下载目录,Apple 官方规定的对外公开位置就是 Documents(需在 manifest.json 开启 UIFileSharingEnabled,见下文配置)。 鸿蒙 DOWNLOAD 模式(API 12+)由系统自动授权 Download/<包名> 目录,返回 URI 具备持久化写权限,用户无感知。

环境要求

  • HBuilderX 4.31+(编译鸿蒙需 4.51+
  • 必须使用自定义基座(标准基座不含 UTS 插件):运行 → 运行到手机或模拟器 → 制作自定义调试基座;打包时用云打包/自有证书打包
  • HarmonyOS:真机需 HarmonyOS NEXT(API 12+)

快速开始

import { downloadToPublic } from '@/uni_modules/lv-downloader/js_sdk/index.js'

const { promise, abort } = downloadToPublic({
  url: 'https://example.com/服务合同.docx',
  fileName: '服务合同.docx',          // 可选,默认从 URL 提取
  headers: { Authorization: 'Bearer xxx' }, // 可选,鉴权下载
  subDir: '律服文档',                  // 可选,公共目录下的子目录
  : (progress, received, total) => {
    console.log(`进度 ${progress}%(${received}/${total})`)
  }
})

promise.then((res) => {
  uni.showToast({ title: '已保存到:' + res.path, icon: 'none' })
}).catch((err) => {
  uni.showToast({ title: err.message, icon: 'none' })
})

// 需要中断下载时
// abort()

把已有本地文件(如缓存、生成文件)转存到公共目录:

import { saveFileToPublic } from '@/uni_modules/lv-downloader/js_sdk/index.js'

saveFileToPublic('_doc/temp/report.pdf', '检测报告.pdf').then((res) => {
  console.log('已保存到', res.path)
})

API

downloadToPublic(options){ promise, abort }

参数 类型 必填 说明
options.url String 网络文件地址
options.fileName String 保存文件名(含扩展名),默认从 URL 提取,自动过滤非法字符
options.headers Object 附加请求头(token 鉴权下载)
options.subDir String 公共目录下的子目录,默认存根目录
options.timeout Number 下载超时毫秒,默认 60000
options.onProgress Function 进度回调 (progress, receivedBytes, totalBytes)
  • promise resolve 值:{ path: 公共目录最终路径, fileName: 文件名 }
  • abort() 中断下载,promise 会 reject「已取消下载」

saveFileToPublic(path, fileName, subDir)Promise

把应用沙盒内的本地文件转存到公共目录,参数同上。

manifest.json 配置

Android 权限(Android 9 及以下兜底需要)

"app-plus": {
  "distribute": {
    "android": {
      "permissions": [
        "<uses-permission android:name=\"android.permission.INTERNET\"/>",
        "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" android:maxSdkVersion=\"28\"/>"
      ]
    }
  }
}

Android 10+ 走 MediaStore,无需存储权限;maxSdkVersion=28 保证不会因此多弹权限申请。

⚠️ 本项目注意:云打包服务会自动注入不带属性的 android.permission.WRITE_EXTERNAL_STORAGE(来自 App 运行时/已选模块/云原生插件)。若再按上面示例手动声明带 maxSdkVersion="28" 的同名权限,Gradle Manifest Merger 会因属性不一致报 duplicated 错误导致打包失败。本项目 manifest.json 中不要再手动添加 WRITE_EXTERNAL_STORAGE,自动注入的声明已足够 Android 9 及以下的运行时权限申请。

iOS「文件」App 可见

"app-plus": {
  "distribute": {
    "ios": {
      "UIFileSharingEnabled": true,
      "LSSupportsOpeningDocumentsInPlace": true
    }
  }
}

配置后用户在系统「文件」App →「我的 iPhone」→ 应用名下即可看到下载的文件,也可通过 iTunes/AirDrop 分享。

HarmonyOS

网络下载需要 ohos.permission.INTERNET(uni-app 鸿蒙工程模板默认已包含;若下载失败请检查生成的鸿蒙工程 entry/src/main/module.json5)。保存公共目录无需任何权限。

实现原理

JS 层(js_sdk/index.js)                UTS 层(utssdk/*/index.uts)
┌─────────────────────────┐           ┌──────────────────────────────┐
│ uni.downloadFile 下载到  │  沙盒路径  │ saveFileToPublicDir:         │
│ 沙盒临时目录(带进度回调)│ ────────→  │  Android: MediaStore → Download│
│ 解析文件名/MIME          │           │  iOS: NSFileManager → Documents│
└─────────────────────────┘           │  鸿蒙: DOWNLOAD 模式 → 公共目录 │
                                      └──────────────────────────────┘
  • Android:API 29+ 用 MediaStore.Downloads 插入记录并流式拷贝(512KB 缓冲,io 线程执行),文件秒级出现在系统「下载」;API 28 及以下直接写 Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS),运行时自动申请权限
  • iOSFileManager 把文件从缓存目录拷到 Documents(同名覆盖);保存成功后 UTS 层直接弹 UIActivityViewController 系统分享面板(NSURL.fileURLWithPath 传真实文件),用户选「存储到文件」可存到任意位置。不走 plus.share.sendWithSystem——其 type:'file' 无法稳定识别文件类型,会退化成文本分享(存出内容为路径字符串的 txt)
  • 鸿蒙DocumentSaveOptions.pickerMode = DocumentPickerMode.DOWNLOAD 静默获取 Download/<包名> 目录授权,fileIo.copyFileSync 完成拷贝

错误码

code 平台 说明
1300002 鸿蒙 用户取消保存
2000 Android 写入异常(IO/权限)
2001-2003 Android 权限申请失败
3001 iOS 读取沙盒源文件失败
3002 iOS 写入 Documents 失败
4000 鸿蒙 写入公共目录失败

常见问题

  1. 点了没反应 / 提示「当前环境不支持」:用的是标准基座。UTS 插件必须自定义基座或正式打包。
  2. 鸿蒙编译报 pickerMode 不存在:鸿蒙 SDK 低于 API 12。升级 DevEco Studio / 鸿蒙 SDK 后重试。
  3. iOS 保存后弹出的系统面板:保存到 Documents 成功后自动弹出,选「存储到文件」即可存到任意位置(我的 iPhone 任意文件夹 / iCloud)。若在面板中左右滑动取消,文件仍保留在 App 的 Documents 中——需基座/云打包的 UIFileSharingEnabled 生效后才会在「文件 App → 我的 iPhone → 应用名」中显示。
  4. Android 9 及以下保存失败:检查 manifest 权限声明(含 maxSdkVersion="28"),并确认用户在权限弹窗中点了允许。
  5. 同名文件:三端均直接覆盖同名旧文件。

目录结构

uni_modules/lv-downloader
├── package.json
├── readme.md
├── changelog.md
├── js_sdk/index.js               # JS 调用层:下载编排 + 进度 + 文件名解析
└── utssdk
    ├── interface.uts             # 跨平台类型定义
    ├── app-android/index.uts     # Android:MediaStore / 直接写入
    ├── app-ios/index.uts          # iOS:NSFileManager → Documents
    └── app-harmony/index.uts      # 鸿蒙:DOWNLOAD 模式 → 公共下载目录

隐私、权限声明

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

Android 9 及以下自动申请 WRITE_EXTERNAL_STORAGE;Android 10+ 与鸿蒙端无需任何存储权限

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

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

许可协议

MIT协议

暂无用户评论。