更新记录

1.3.0(2026-08-03) 下载此版本

新增

  • 内置模拟数据模块 mock.js,无真实接口也可演示保存 / 分享。
  • 核心不变mockFetchExcelExport / createMockXlsxBuffer,模拟接口返回表格文件流并保存 / 分享为 .xlsx
  • 大文件 / 大图 mock:mockFetchLargeFilemockFetchLargeImagecreateMockLargeFileBuffercreateMockLargeImageBuffercreateMockLargeXlsxBuffer
  • 同步提供:MOCK_FILESmockFetchFileListmockFetchExportFilecreateMockBufferformatBytes 等。
  • 本地生成 XLSX / TXT / CSV / PDF / BMP / BIN,不依赖外网。
  • 跨端兼容:Vue2/3、H5、App-vue、nvue、Android、iOS、鸿蒙(APP-HARMONY + harmony.js)、uni-app x(utssdk/)。

修复

  • 修复 Android 10+ 保存到公共 Download 时 resolver.insert is not a functionContentResolverplus.android.invoke 兜底)。
  • 修复鸿蒙不会命中 APP-PLUS 导致保存 / 分享空实现的问题。

优化

  • Demo 分区:核心表格 → 大文件/大图 → 其它小文件 → 在线 URL / 文本流;大资源首次生成后缓存。
  • 大文件生成改为分块填充,降低首击卡顿。
  • waitPlusReady 不再强依赖 document,nvue 可就绪;iOS 分享取最上层 ViewController。
  • ArrayBuffer 检测兼容跨 realm,并支持 TypedArray 入参。
  • 平台矩阵与文档对齐真实支持范围(小程序仍不支持系统级文件分享)。
  • 文档导入路径统一为 @/uni_modules/lf-file-share

V1.2.2(2026-05-29) 下载此版本

新增

  • 新增 saveDirName,支持自定义保存目录,例如 Download/HugeAuto/文件名
  • 新增 saveLocation: 'sandbox',用于兼容保存到 APP 沙盒目录的场景。
  • 新增 debug 调试参数,可打印 Base64 转换、文件写入、文件校验等耗时日志。
  • 新增文件名后缀自动补齐能力,可根据 mime测试文档 自动保存为 测试文档.pdf

修复

  • 修复 APP 端保存较大 ArrayBuffer 文件时可能出现空文件的问题。
    • 典型报错:文件大小不一致:expect=xxx, actual=0
  • 修复 Android 使用 _downloads/ 时文件实际保存到 Android/data/包名/downloads 私有目录,用户在文件管理器中不易找到的问题。
  • 修复部分 Android/HBuilder 环境公共下载目录解析为空,导致 getAbsolutePath of null 的问题。
  • 修复部分 Android/HBuilder 环境查询 DownloadManager 状态时 cursor.moveToFirst is not a function 的兼容问题。

优化

  • Android appAction: 'save' 默认保存到系统公共 Download/下载 目录。
  • 在线 URL 保存优先使用系统下载能力,适合 CDN/OSS 等远程文件。
  • 接口文件流保存使用 ArrayBuffer -> Base64 -> 分片写入,提升大文件保存稳定性。
  • 移除逐字节 JS -> Native 写入兜底,避免 1MB+ 文件保存耗时过长。
  • 保持原有分享逻辑兼容:旧代码不传 appAction 时仍默认走系统分享。

V1.2.1(2026-05-28) 下载此版本

  • 修复部分 APP 环境中较大 ArrayBuffer 调用 uni.arrayBufferToBase64 后可能得到空内容,导致保存时报 文件大小不一致:actual=0 的问题。
  • 新增 ArrayBuffer 转 Base64 分片兜底逻辑。
  • 新增 Base64 字节长度校验,避免空文件被写入。
查看更多

平台兼容性

uni-app(5.07)

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

uni-app x(5.07)

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

文件下载与系统分享

将接口返回的 ArrayBuffer、在线 URL 保存到本地,或调起系统分享。兼容 Vue2/3、H5、App-vue、nvue、Android、iOS、鸿蒙、uni-app x。


平台支持

运行时 支持 说明
Vue2 / Vue3 纯 JS API
H5 Blob 下载
App-vue / nvue Android / iOS
Android FileProvider 分享;公共 Download 保存
iOS 系统分享面板;沙盒保存
鸿蒙 NEXT getFileSystemManager 写入与打开
uni-app x utssdk/
小程序 - 无系统级文件分享 / 公共目录能力

引入

import {
  downloadOrShareArrayBuffer,
  downloadOrShareByUrl,
  shareOnlineImage,
  shareOnlineVideo,
  shareResource,
  getResourceTypeByFilename,
  // 无真实接口时可用 mock
  mockFetchExcelExport,
  mockFetchExportFile,
  mockFetchLargeFile,
  mockFetchLargeImage,
  mockFetchFileList
} from '@/uni_modules/lf-file-share'

uni-app x 同样从 @/uni_modules/lf-file-share 引入,API 名称一致。


快速上手

1. 接口返回表格文件流 → 保存 / 分享

const res = await uni.request({
  url: 'https://your.api/export/excel',
  method: 'GET',
  responseType: 'arraybuffer'
})

// 保存
await downloadOrShareArrayBuffer(res.data, '销售报表.xlsx', {
  appAction: 'save',
  mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  saveDirName: 'MyApp'
})

// 分享
await downloadOrShareArrayBuffer(res.data, '销售报表.xlsx', {
  appAction: 'share',
  mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  chooserTitle: '分享表格'
})

无后端时可用 mock(等价于 responseType: 'arraybuffer'):

const res = await mockFetchExcelExport({ filename: '销售报表.xlsx' })

await downloadOrShareArrayBuffer(res.data, res.filename, {
  mime: res.mime,
  appAction: 'save',
  saveDirName: 'MyApp'
})

2. 在线文件 URL → 保存 / 分享

await downloadOrShareByUrl('https://example.com/test.pdf', {
  filename: '说明文档.pdf',
  mime: 'application/pdf',
  appAction: 'save',
  saveDirName: 'MyApp'
})

await downloadOrShareByUrl('https://example.com/test.pdf', {
  filename: '说明文档.pdf',
  mime: 'application/pdf',
  appAction: 'share',
  chooserTitle: '分享 PDF'
})

3. 在线图片 / 视频

await shareOnlineImage('https://example.com/a.png', {
  appAction: 'share'
})

await shareOnlineVideo('https://example.com/a.mp4', {
  appAction: 'save',
  saveDirName: 'MyApp',
  filename: '演示视频.mp4'
})

4. 统一入口

// 文件流
await shareResource({
  buffer,
  filename: '报表.xlsx',
  appAction: 'save',
  mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})

// 在线地址
await shareResource({
  url: 'https://example.com/test.pdf',
  filename: '文档.pdf',
  appAction: 'save',
  mime: 'application/pdf'
})

5. 大文件 / 大图 mock(压测)

const bigFile = await mockFetchLargeFile()
await downloadOrShareArrayBuffer(bigFile.data, bigFile.filename, {
  mime: bigFile.mime,
  appAction: 'share'
})

const bigImage = await mockFetchLargeImage()
await downloadOrShareArrayBuffer(bigImage.data, bigImage.filename, {
  mime: bigImage.mime,
  appAction: 'share'
})

API

downloadOrShareArrayBuffer(buffer, filename, options)

处理接口返回的二进制文件流(Excel / PDF / ZIP 等)。

downloadOrShareByUrl(url, options)

处理在线文件地址(OSS / CDN / 直链)。

shareOnlineImage(url, options) / shareOnlineVideo(url, options)

在线图片、视频的快捷方法。

shareResource(params)

传入 bufferurl,内部自动分流。

getResourceTypeByFilename(filename, mime)

根据文件名 / MIME 判断 image / video / file


参数

appAction

说明
share 默认。写入后调起系统分享
save 只保存到本地并返回路径,不调起分享

不传时默认为 share

常用 options

字段 类型 默认值 说明
appAction string share share / save
filename string 自动推断 URL 场景建议显式传入
mime string 按扩展名推断 建议保存时显式传入
chooserTitle string 分享文件 系统分享面板标题
saveDirName string file_save 保存目录名
shareDirName string share_temp 分享临时目录名
saveLocation string public Android:public 公共 Download;sandbox 应用沙盒
debug boolean false 打印转换 / 写入耗时

返回值

{
  platform: 'H5' | 'Android' | 'iOS' | 'Harmony',
  action: 'download' | 'share' | 'save',
  path: string,       // APP 本地绝对路径;H5 可能为空
  localPath: string,  // 相对路径,如 Download/MyApp/a.pdf
  filename: string,
  size: number,
  isPublic: boolean   // 是否 Android 公共下载目录
}

页面示例

<script setup>
import {
  downloadOrShareArrayBuffer,
  downloadOrShareByUrl
} from '@/uni_modules/lf-file-share'

const handleSaveExcel = async () => {
  try {
    const res = await uni.request({
      url: 'https://example.com/export',
      method: 'GET',
      responseType: 'arraybuffer'
    })

    const result = await downloadOrShareArrayBuffer(res.data, '报表.xlsx', {
      appAction: 'save',
      saveDirName: 'MyApp',
      mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      debug: true
    })

    uni.showToast({ title: '保存成功', icon: 'success' })
    console.log(result.path)
  } catch (e) {
    uni.showToast({ title: e.message || '保存失败', icon: 'none' })
  }
}

const handleSharePdf = async () => {
  try {
    await downloadOrShareByUrl('https://example.com/test.pdf', {
      appAction: 'share',
      filename: '说明文档.pdf',
      mime: 'application/pdf',
      chooserTitle: '分享 PDF'
    })
  } catch (e) {
    uni.showToast({ title: e.message || '分享失败', icon: 'none' })
  }
}
</script>

保存路径

Android

appAction: 'save' 默认保存到公共下载目录:

/storage/emulated/0/Download/{saveDirName}/文件名

需要写入应用沙盒时:

await downloadOrShareByUrl(url, {
  appAction: 'save',
  saveLocation: 'sandbox',
  filename: '测试文档.pdf',
  mime: 'application/pdf'
})

iOS / 鸿蒙

默认写入应用可访问的用户数据目录(沙盒)。若需在系统「文件」中直接可见,需按各端原生配置开启文件共享能力。


Mock 文件 id

id 说明
xlsx-report 销售报表 XLSX
large-xlsx 约 1500 行大表格
large-image 约 2.6MB 大图
large-file 约 2.5MB 二进制文件
csv-orders 订单 CSV
pdf-demo 极简 PDF
txt-report 文本报告
const res = await mockFetchExportFile('pdf-demo')
await downloadOrShareArrayBuffer(res.data, res.filename, {
  mime: res.mime,
  appAction: 'save'
})

MIME 参考

类型 MIME
PDF application/pdf
XLSX application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
XLS application/vnd.ms-excel
DOCX application/vnd.openxmlformats-officedocument.wordprocessingml.document
ZIP application/zip
TXT text/plain
CSV text/csv
PNG / JPG image/png / image/jpeg
MP4 video/mp4

未带后缀的 filename 会按 mime 自动补齐扩展名。


权限

Android

Android 10+ 保存公共 Download 时优先走系统媒体库 / 下载能力。
Android 9 及以下写入外部公共目录时,需在 manifest.json 配置:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

iOS

无强制存储权限;默认写入 App 沙盒。


常见问题

不传 appAction 会怎样?
默认为 share,会调起系统分享。

save 会不会弹分享面板?
不会,只保存并返回路径。

保存成功后如何打开文件?

// #ifdef APP-PLUS
plus.runtime.openFile(result.path, {}, () => {
  uni.showToast({ title: '未找到可打开此文件的应用', icon: 'none' })
})
// #endif

保存失败怎么排查?

try {
  const result = await downloadOrShareByUrl(url, {
    appAction: 'save',
    filename: 'test.pdf',
    mime: 'application/pdf',
    debug: true
  })
  console.log(result.path)
} catch (e) {
  console.error(e)
  uni.showToast({ title: e.message || '保存失败', icon: 'none' })
}

大文件保存注意什么?
接口务必 responseType: 'arraybuffer';可开 debug: true 查看 Base64 转换与写入耗时;按钮加 loading,避免重复点击。


注意事项

  1. 接口文件流必须使用 responseType: 'arraybuffer'
  2. 保存 PDF / Excel 时建议显式传对应 mime
  3. 在线 URL 需可正常访问。
  4. Android 系统分享依赖原生 FileProvider 配置。
  5. iOS / 鸿蒙默认保存目录与 Android 公共 Download 不同。

隐私、权限声明

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

### Android Android 10+ 保存公共 `Download` 时优先走系统媒体库 / 下载能力。 Android 9 及以下写入外部公共目录时,需在 `manifest.json` 配置: ```xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ``` ### iOS 无强制存储权限;默认写入 App 沙盒。

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

本插件处理宿主应用传入的 ArrayBuffer、URL、文件名、MIME 和平台类型,用于文件下载、本地写入与系统分享;不采集设备标识,不内置行为追踪,不主动向固定服务器发送数据。

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

许可协议

MIT License

Copyright (c) 2026

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.