uni-app多端资源文件下载实现方案

一、背景介绍

在开发 uni-app 应用时,经常需要实现文件下载功能。但由于不同平台(H5、小程序、App)的运行环境和API差异,我们需要采用条件编译来实现跨平台的文件下载功能。

二、平台差异分析

2.1 H5平台特点

  • 运行在浏览器环境中

  • 可以使用浏览器原生的 XMLHttpRequest 和 Blob API

  • 通过创建临时 <a />标签下载

  • 受同源策略限制,需要注意跨域问题

2.2 小程序和App平台特点

  • 运行在原生环境中
  • 使用平台提供的专有API
  • 需要申请相关权限
  • 可以监听下载进度
  • 下载完成后需要调用特定API保存到相册

三、实现方案

3.1 H5端实现

js 复制代码
async function saveFileToLocal(fileUrl) {
    // #ifdef H5
    uni.showLoading({
      title: '正在下载中...',
      mask: true
    })
    const xhr = new XMLHttpRequest();
    xhr.open('GET', fileUrl, true);
    xhr.responseType = 'arraybuffer';    // 返回类型blob
    xhr.onload = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        let blob = this.response;
        // 转换为blob链接
        let url = window.URL.createObjectURL(
          new Blob([blob], { 
            type: 'video/mp4'  // 根据文件类型设置
          })
        )
        // 创建临时下载链接
        let a = document.createElement('a');
        a.download = 'filename';  // 设置下载文件名
        a.href = url;
        a.style.display = 'none';
        document.body.appendChild(a);
        a.click();
        uni.hideLoading();
        document.body.removeChild(a);
      }
    };
    xhr.send();
    // #endif
}

3.2 小程序和App实现

js 复制代码
async function saveFileToLocal(fileUrl) {
    // #ifndef H5
    return new Promise((resolve, reject) => {
      // 下载状态控制
      isDownloading.value = true;
      downloadProgress.value = 0;

      const downloadTask = uni.downloadFile({
        url: fileUrl,
        success: (res) => {
          if (res.statusCode === 200) {
            // 下载成功后保存到相册
            uni.saveVideoToPhotosAlbum({
              filePath: res.tempFilePath,
              success: () => {
                uni.showToast({
                  title: '保存成功',
                  icon: 'success'
                });
                resolve('保存成功');
              },
              fail: (err) => {
                uni.showToast({
                  title: '保存失败',
                  icon: 'none'
                });
                reject(err);
              }
            });
          }
        },
        fail: (err) => {
          uni.showToast({
            title: '下载失败',
            icon: 'none'
          });
          reject(err);
        },
        complete: () => {
          isDownloading.value = false;
          downloadProgress.value = 0;
        }
      });

      // 监听下载进度
      downloadTask.onProgressUpdate((res) => {
        downloadProgress.value = res.progress;
      });
});
// #endif
}

四、条件编译说明

uni-app 使用条件编译来处理平台差异:

  • // #ifdef H5:仅在 H5 平台编译
  • // #ifndef H5:除了 H5 平台都编译
  • // #endif:条件编译结束标志 这样做的原因:
  1. API差异:不同平台提供的API不同
  2. 运行环境差异:H5运行在浏览器中,而小程序和App运行在各自的容器中
  3. 安全限制差异:不同平台有不同的安全策略
  4. 用户体验优化:可以针对不同平台提供最优的实现方案

五、实现细节解析

5.1 H5端实现要点

  1. 使用 XMLHttpRequest 请求文件数据
  2. 设置 responseType 为 arraybuffer
  3. 使用 Blob 创建临时URL
  4. 通过动态创建 <a /> 标签元素触发下载
  5. 下载完成后清理临时元素

5.2 小程序和App实现要点

  1. 使用 uni.downloadFile 下载文件
  2. 使用 uni.saveVideoToPhotosAlbumuni.saveImageToPhotosAlbum保存文件
  3. 实现下载进度监听
  4. 完善的状态管理和错误处理
  5. 注意权限申请

5.3 权限说明

1.Android权限解释:

  • WRITE_EXTERNAL_STORAGE: 写入外部存储权限
  • READ_EXTERNAL_STORAGE: 读取外部存储权限
  • INTERNET: 网络访问权限
  • MOUNT_UNMOUNT_FILESYSTEMS: 挂载文件系统权限
  • MANAGE_EXTERNAL_STORAGE: Android 10及以上的存储权限
  • MEDIA_CONTENT_CONTROL: 媒体文件控制权限

六、注意事项

1.权限处理

  • 小程序需要在 manifest.json 中声明相关权限
  • App 需要动态申请存储权限
  • H5 需要注意跨域问题

2.文件类型

  • 图片:image/jpeg、image/png 等
  • 视频:video/mp4 等
  • 需要根据实际文件类型设置正确的 MIME type

3.错误处理

  • 网络错误
  • 权限拒绝
  • 存储空间不足
  • 文件格式不支持

4.用户体验

  • 添加下载进度提示
  • 适当的 loading 提示
  • 成功/失败的反馈

七、最佳实践建议

  1. 封装统一的下载方法,内部根据平台调用不同实现
  2. 添加完善的错误处理和状态管理
  3. 实现下载进度提示
  4. 注意内存管理,及时清理临时文件
  5. 考虑网络状态和存储空间检查

八、总结

条件编译实现多端文件下载是一个很好的跨平台解决方案。它让我们能够:

  1. 充分利用各平台特性
  2. 提供最佳的用户体验
  3. 保持代码的可维护性
  4. 实现统一的业务逻辑

这篇文章能帮助你更好地理解和实现uni-app多端文件下载功能!

相关推荐
B站_计算机毕业设计之家5 分钟前
豆瓣电影数据采集分析推荐系统 | Python Vue Flask框架 LSTM Echarts多技术融合开发 毕业设计源码 计算机
vue.js·python·机器学习·flask·echarts·lstm·推荐算法
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
游戏开发爱好者82 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
我是伪码农2 小时前
Vue 2.3
前端·javascript·vue.js
跳动的梦想家h3 小时前
环境配置 + AI 提效双管齐下
java·vue.js·spring
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
2501_915106323 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_915106324 小时前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
一 乐4 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
科技D人生4 小时前
Vue.js 学习总结(20)—— Vue-Office 实战:word、pdf、excel、ppt 多种文档的在线预览
vue.js·word·vue-pdf·stylesheet·docx-preview·vue-office