更新记录

1.0.0(2026-07-15)

[1.0.0] - 2025-07-15

首次发布

新增

  • 三端文件下载保存:统一 saveRemoteFile() API,一次调用覆盖 Android / iOS / HarmonyOS
  • Android MediaStore 分区存储:Android 10+ 使用 MediaStore.Downloads 写入系统下载目录,无需存储权限
  • Android 传统文件系统兼容:Android 9 及以下自动降级为 Environment.DIRECTORY_DOWNLOADS + WRITE_EXTERNAL_STORAGE
  • iOS 系统分享面板:文件保存至 Documents 目录后弹出 UIActivityViewController,用户自主选择目标 App
  • HarmonyOS 文件选择器:弹出系统选择器,用户自主选择保存位置
  • HTTPS 自签名证书跳过trustAllCerts: true 支持,适配内网环境(Android 使用自定义 SSLContext + hybrid.kt 混编;iOS 使用 URLSession delegate)
  • Content-Disposition 文件名解析:完整支持 RFC 5987 百分号编码 UTF-8 文件名(如 filename*=UTF-8''%E6%8A%A5%E5%91%8A.pdf报告.pdf
  • MIME 类型扩展名推断:根据 Content-Type 自动推断文件扩展名(支持 20+ 常见类型)
  • 文件名自动重名序号:同名文件自动追加 (1)(2) 序号,永不覆盖已有文件
  • 下载进度回调progress 回调实时返回下载百分比(0–100)
  • 自定义 HTTP 请求头headers 参数支持鉴权 Token、Cookie 等
  • 磁盘空间预检:保存前检查剩余空间(至少 10MB 阈值)
  • 自动打开文件autoOpen: true 保存后调用系统默认应用打开(Android)
  • 请求超时配置timeout 参数,默认 30 秒
  • 后台线程下载:Android 端网络请求与文件写入均在后台线程,不阻塞 UI
  • hybrid.kt 原生混编:通过 DCloud 官方 hybrid.kt 机制实现 X509TrustManager(UTS 语法无法表达 Java 协变数组形参的解决方案)

技术亮点

  • **

平台兼容性

uni-app x(4.0)

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

其他

多语言 暗黑模式 宽屏模式
× ×

liyq-down-save

一行代码,三端通用 · 把远程文件真正存进用户能找到的系统目录

🌟 特别适合:企业内网、私有化部署、HTTPS 自签名证书服务器的文件下载场景

saveRemoteFile 是一款基于 UTS(uni TypeScript) 的原生插件,一行调用即可完成「下载 + 保存」全流程,覆盖 Android / iOS / HarmonyOS 三端。插件内置网络请求、文件名智能解析、分区存储适配、权限兼容、进度回调等全部细节——你只管传 URL,剩下的交给它。

适用场景:内网资源拉取、私有化部署文件分发、自签名证书服务器下载、报表导出、附件下载、图片/视频保存、PDF 文档归档……


为什么选择 liyq-down-save?

如果你用过 uni.downloadFile + uni.saveFile,一定踩过这些坑:

你正在忍受的痛点 liyq-down-save 的解决方案
下载后文件存进 App 私有目录,用户根本找不到 直达系统级目录——Android 存入 Downloads,用户在「文件管理」直接可见
Android 10/11/12/13 分区存储适配,改到怀疑人生 内置 MediaStore 方案,自动适配全版本,Android 10+ 甚至免存储权限
同名文件直接覆盖,用户重要文件不翼而飞 自动追加序号(报告(1).pdf报告(2).pdf),永不覆盖
内网自签名 HTTPS,下载直接报错握手失败 trustAllCerts: true 一键放行,内网部署零障碍
服务端 Content-Disposition 中文文件名乱码成 %E6%8A%A5… 自动解析 RFC 5987 百分号编码,正确还原「季度报告.pdf」
三端 API 各写一遍,行为还不一致 一套 API 三端通用,各自遵循原生交互习惯
大文件下载卡死 UI,进度条根本转不动 全程后台线程 + 实时进度回调,丝滑不卡顿

🌟 内网与自签名证书下载(核心特色)

这是 liyq-down-save 区别于普通下载插件的核心能力。

痛点:企业内网下载的死结

大量企业级应用部署在内网或私有云环境,出于成本和运维考虑,常使用 HTTPS 自签名证书IP 直连非标准域名 等方式。此时标准下载方案会直接报错:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: 
Trust anchor for certification path not found.
NSURLSession/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

uni.downloadFile 和大多数插件无法绕过这个限制——因为它们依赖系统默认的证书校验链,而自签名证书不在系统信任列表中。

方案:trustAllCerts 一键放行

liyq-down-save 在三端原生层实现了证书校验的旁路:

saveRemoteFile({
  url: 'https://192.168.1.100:8443/api/export/report',  // IP 直连 + 自签证书
  trustAllCerts: true,                                    // 一键放行
  headers: {
    'Authorization': 'Bearer internal-token'              // 内网鉴权
  },
  saveName: '月度报表.xlsx',
  success: (path) => {
    console.log('内网文件已保存:', path)
  }
})

三端实现机制

平台 旁路机制 说明
Android 自定义 SSLContext + X509TrustManager(hybrid.kt 原生混编) 替换默认 SSLSocketFactory,信任所有证书;同时放行 HostnameVerifier 解决域名不匹配
iOS URLSessionDelegate 实现 urlSession(_:didReceive:completionHandler:) 在证书校验回调中返回 .useCredential,接受自签名证书
HarmonyOS 系统网络栈配置 按鸿蒙安全模型处理

典型适用场景

场景 说明
企业内网 OA / ERP 内部系统常用自签证书,标准方案无法下载导出的报表
私有化部署 客户自建服务器,证书未走公共 CA
开发 / 测试环境 本地开发服务器使用临时自签证书
IP 直连 无域名或使用 IP 访问,触发 Hostname 不匹配
物联网设备 局域网内设备提供的 HTTPS 服务

⚠️ 安全提醒trustAllCerts 会跳过全部 HTTPS 证书校验,仅限可信内网环境使用。公网请求请保持默认 false,避免中间人攻击风险。插件设计上此选项默认关闭,需显式开启。


平台支持

平台 支持状态 保存位置 交互方式
Android (uni-app-x) 系统 Downloads 目录 静默保存,可选自动打开
iOS (uni-app-x) App Documents 目录 系统分享面板(用户选择目标 App)
HarmonyOS (uni-app-x) 用户选择 系统文件选择器(用户选择保存位置)
Android (uni-app) 需 uni-app-x
iOS (uni-app) 需 uni-app-x
H5 / 小程序 非原生场景

最低版本要求:HBuilderX 3.6.8+,uni-app-x 3.1.0+


快速开始

安装

liyq-down-save 插件从 DCloud 插件市场导入,或手动将 liyq-down-save/ 目录放入项目的 uni_modules/ 目录下。

三秒上手

import { saveRemoteFile } from '@/uni_modules/liyq-down-save'

saveRemoteFile({
  url: 'https://example.com/report.pdf',
  success: (path) => {
    console.log('保存成功:', path)
  },
  fail: (errMsg) => {
    console.error('保存失败:', errMsg)
  }
})

API 文档

saveRemoteFile(options)

下载远程文件并保存到系统目录。

参数

属性 类型 必填 默认值 说明
url string 远程文件 URL(支持 HTTP / HTTPS)
saveName string 自动推断 指定保存文件名(含扩展名)。留空时从 URL / Content-Disposition 自动推断
autoOpen boolean false 保存完成后是否自动用系统默认应用打开文件(仅 Android)
trustAllCerts boolean false 是否跳过 HTTPS 证书校验(用于内网自签名证书环境)
headers Object {} 自定义 HTTP 请求头(如鉴权 Token、Cookie 等)
timeout number 30000 请求超时时间(毫秒)
checkStorage boolean true 保存前是否检查磁盘剩余空间(至少 10MB)
success function 成功回调,参数为文件保存路径 string
fail function 失败回调,参数为错误描述 string
progress function 下载进度回调,参数 { progress: number },范围 0–100

文件名推断优先级

saveName(显式指定)
  ↓ 未指定
Content-Disposition 响应头(解析 RFC 5987 百分号编码 + UTF-8)
  ↓ 未包含
URL 路径最后一段
  ↓ 无法推断
"download" + MIME 类型推断的扩展名

使用示例

基础下载

saveRemoteFile({
  url: 'https://example.com/document.pdf'
})

指定文件名 + 自动打开

saveRemoteFile({
  url: 'https://example.com/report.pdf',
  saveName: '2024年度报告.pdf',
  autoOpen: true,
  success: (path) => {
    uni.showToast({ title: '已保存到 Downloads' })
  }
})

带下载进度条

saveRemoteFile({
  url: 'https://example.com/large-video.mp4',
  saveName: '演示视频.mp4',
  progress: (data) => {
    console.log(`下载进度:${data.progress}%`)
    uni.showLoading({ title: `${data.progress}%`, mask: true })
  },
  success: (path) => {
    uni.hideLoading()
    uni.showToast({ title: '下载完成' })
  },
  fail: (err) => {
    uni.hideLoading()
    uni.showToast({ title: err, icon: 'none' })
  }
})

企业内网自签名证书 + 鉴权(👉 核心场景)

企业内网、私有化部署、IP 直连服务器的下载场景,trustAllCerts: true 一键解决证书握手失败:

saveRemoteFile({
  url: 'https://internal.company.com:8443/api/export',  // 自签证书 + 非标端口
  trustAllCerts: true,                                   // 跳过证书校验
  headers: {
    'Authorization': 'Bearer your-internal-token',       // 内网鉴权
    'X-Custom-Header': 'value'
  },
  success: (path) => {
    console.log('内网文件已保存:', path)
  }
})

Content-Disposition 自动文件名

服务端响应头包含 Content-Disposition: attachment; filename*=UTF-8''%E6%8A%A5%E5%91%8A.pdf 时,插件自动解码为「报告.pdf」,无需手动指定 saveName


各平台行为说明

Android

  • Android 10 (Q) 及以上:通过 MediaStore.Downloads 写入系统下载目录,零权限,文件在系统「文件管理 → 下载」中直接可见
  • Android 9 及以下:降级为传统文件系统方案,写入 Environment.DIRECTORY_DOWNLOADS,需声明 WRITE_EXTERNAL_STORAGE(插件已在配置中限定 maxSdkVersion=28
  • 重名保护:检测到同名文件时自动追加序号(报告(1).pdf报告(2).pdf),绝不覆盖已有文件
  • autoOpen:保存后通过 FileProvider + Intent 调起系统默认应用直接打开

iOS

  • 文件先下载至 App 的 Documents 目录
  • 随即弹出系统分享面板(UIActivityViewController),由用户自主选择去向——「文件」App、微信、邮件、AirDrop……
  • 完全遵循 iOS 原生交互习惯,把选择权交给用户,审核无忧

HarmonyOS

  • 调起系统文件选择器,由用户主动选择保存位置
  • 下载完成后写入用户选定的路径,全程透明可控
  • 符合鸿蒙系统的隐私安全规范

权限配置

Android 权限

manifest.jsonApp 模块配置 中确认以下权限:

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

WRITE_EXTERNAL_STORAGE 设有 maxSdkVersion=28,仅在 Android 9 及以下生效。Android 10+ 使用 MediaStore 无需此权限。

iOS / HarmonyOS

无需额外权限配置。


技术特性

内网 HTTPS 自签名证书旁路

详见上方 🌟 内网与自签名证书下载(核心特色) 章节。

通过 trustAllCerts: true,Android 端经 hybrid.kt 原生混编注入自定义 SSLContext + X509TrustManager + HostnameVerifier;iOS 端通过 URLSessionDelegate 接受自签名证书。完整覆盖企业内网、私有化部署、IP 直连等证书握手失败场景。

Content-Disposition 解析

完整支持 RFC 5987 标准:

  • filename*=UTF-8''%E6%8A%A5%E5%91%8A.pdf(百分号编码 UTF-8 文件名)
  • filename="report.pdf"(ASCII 文件名)
  • 自动处理百分号解码与 UTF-8 字符串重建

MIME 类型推断

当文件名无扩展名时,根据 HTTP 响应头的 Content-Type 自动推断扩展名:

Content-Type 扩展名
application/pdf .pdf
image/jpeg .jpg
image/png .png
video/mp4 .mp4
application/zip .zip
application/json .json
text/html .html
audio/mpeg .mp3
... ...

常见问题

Q: 下载大文件时会阻塞 UI 吗?

不会。 Android 端使用后台线程执行网络请求和文件写入;iOS 端使用 URLSession 异步回调;HarmonyOS 端同样使用异步 API。全程不阻塞主线程。

Q: 支持断点续传吗?

当前版本(1.x)暂不支持断点续传。大文件下载如需断点续传能力,可在 fail 回调中记录进度,重新发起请求时通过 headers 传入 Range 头实现(需服务端支持)。

Q: trustAllCerts 安全吗?用在什么场景?

trustAllCerts 是为企业内网、私有化部署、自签名证书服务器量身定制的核心能力——这些场景下证书未走公共 CA,标准下载方案会直接握手失败。它会跳过 HTTPS 证书校验,因此仅限可信内网环境使用,公网请求请保持默认 false。插件设计上此选项默认关闭,需显式开启,避免误用。

Q: iOS 为什么不直接保存到"文件"App?

iOS 沙盒机制下,App 无法直接写入系统级目录。标准做法是先保存到 App Documents 目录,再通过系统分享面板让用户选择目标。这是 iOS 平台的系统限制,所有合规 App 均遵循此模式。

Q: 如何反馈 Bug 或申请功能?

请通过 DCloud 插件市场的「问答反馈」或直接联系作者。


版本更新

详见 changelog.md

售后与支持

  • Bug 修复:购买后可终身享受 Bug 修复更新
  • 使用咨询:通过 DCloud 插件市场「问答反馈」联系作者,通常 24 小时内响应
  • 功能建议:欢迎提交需求,优先级高的功能将在后续版本中实现

授权许可

版本 价格 授权范围
标准版 ¥69.90 编译产物,可在任意数量个人/企业项目中使用
源码版 ¥199.00 完整源码,可自由修改、二次开发、定制功能

授权说明:购买即授权在任意数量项目中使用。源码版可自由修改与二次开发。禁止转售、重新分发或上传至其他插件市场。

隐私、权限声明

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

Android 9 及以下需要 WRITE_EXTERNAL_STORAGE 权限(maxSdkVersion=28),Android 10+ 无需任何权限

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

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

暂无用户评论。