更新记录
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) |
promiseresolve 值:{ 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),运行时自动申请权限 - iOS:
FileManager把文件从缓存目录拷到 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 | 鸿蒙 | 写入公共目录失败 |
常见问题
- 点了没反应 / 提示「当前环境不支持」:用的是标准基座。UTS 插件必须自定义基座或正式打包。
- 鸿蒙编译报
pickerMode不存在:鸿蒙 SDK 低于 API 12。升级 DevEco Studio / 鸿蒙 SDK 后重试。 - iOS 保存后弹出的系统面板:保存到 Documents 成功后自动弹出,选「存储到文件」即可存到任意位置(我的 iPhone 任意文件夹 / iCloud)。若在面板中左右滑动取消,文件仍保留在 App 的 Documents 中——需基座/云打包的
UIFileSharingEnabled生效后才会在「文件 App → 我的 iPhone → 应用名」中显示。 - Android 9 及以下保存失败:检查 manifest 权限声明(含
maxSdkVersion="28"),并确认用户在权限弹窗中点了允许。 - 同名文件:三端均直接覆盖同名旧文件。
目录结构
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 模式 → 公共下载目录

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 0
赞赏 0
下载 12573880
赞赏 1949
赞赏
京公网安备:11010802035340号