uniapp下载文件--支持H5和小程序

uniapp下载文件--支持H5和小程序

前言​

在 Uniapp 跨端开发中,文件下载是高频需求(如 PDF 报表、Excel 数据、图片等),但 H5 与小程序的运行环境差异极大:小程序有独立的文件系统,而 H5 依赖浏览器原生能力,直接复用代码会出现兼容性问题。本文将详细拆解两者的实现逻辑,提供一套兼容两端的完整方案,附代码示例和避坑指南。​

一、核心差异:H5 与小程序下载机制对比​

特性​

H5 环境​

小程序环境(微信 / 支付宝等)​

核心 API​

浏览器原生 a 标签、XMLHttpRequest​

uni.downloadFile + uni.saveFile​

文件存储​

无本地文件系统,需用户手动保存​

支持临时文件 + 永久文件存储​

跨域限制​

受浏览器 CORS 政策严格限制​

需配置合法域名,跨域由微信后台处理​

进度监听​

需通过原生 progress 事件实现​

uni.downloadFile 自带 onProgressUpdate​

文件打开​

依赖浏览器默认行为(新标签页打开)​

uni.openDocument 支持本地打开​

二、通用前置准备(两端都需注意)​

  1. 跨域配置:​
  • 小程序:登录对应平台后台(如微信公众平台),在「开发设置」中添加下载地址的合法域名(downloadFile 域名)。​
  • H5:后端需配置 CORS 响应头(A***ess-Control-Allow-Origin: *、A***ess-Control-Allow-Methods: GET 等),否则跨域下载失败。​
  1. 权限说明:​
  • 小程序无需额外授权,H5 依赖浏览器下载权限(无需手动申请)。​
  1. 文件格式支持:​

主流格式(PDF、doc、xls、jpg、png)均支持,特殊格式(如 .zip)需结合对应解析工具。​

三、分场景实现方案​

场景 1:基础下载(下载后保存 / 打开文件)​

3.1 小程序端实现(推荐 downloadFile + saveFile)​

/**
 * 小程序下载文件
 * @param {String} url - 下载地址
 * @param {String} fileName - 自定义文件名
 */
miniProgramDownload(url, fileName = '文件') {
  uni.showLoading({ title: '下载中...' });

  // 1. 下载文件到临时路径
  uni.downloadFile({
    url: url,
    header: {
      // 如需携带登录态,添加 Token(示例)
      // 'Authorization': 'Bearer ' + uni.getStorageSync('token')
    },
    // 监听下载进度
    onProgressUpdate: (res) => {
      console.log(`下载进度:${res.progress}%`);
      // 可结合进度条组件实时展示
    },
    su***ess: (downloadRes) => {
      // 下载成功(状态码 200)
      if (downloadRes.statusCode === 200) {
        // 2. 保存文件到本地(永久路径,避免临时文件被清理)
        uni.saveFile({
          tempFilePath: downloadRes.tempFilePath,
          su***ess: (saveRes) => {
            uni.hideLoading();
            uni.showToast({ title: '下载成功', icon: 'su***ess' });
            
            // 3. 打开文件(可选,支持 PDF/文档等)
            this.openFile(saveRes.savedFilePath);
          },
          fail: (err) => {
            uni.hideLoading();
            uni.showToast({ title: '保存失败', icon: 'none' });
            console.error('保存失败:', err);
          }
        });
      } else {
        uni.hideLoading();
        uni.showToast({ title: `下载失败:${downloadRes.statusCode}`, icon: 'none' });
      }
    },
    fail: (err) => {
      uni.hideLoading();
      uni.showToast({ title: '下载失败', icon: 'none' });
      console.error('下载失败:', err);
    }
  });
},

// 打开已下载的文件
openFile(filePath) {
  uni.openDocument({
    filePath: filePath,
    showMenu: true, // 显示右上角菜单(支持转发、保存到手机)
    su***ess: () => console.log('文件打开成功'),
    fail: (err) => {
      uni.showToast({ title: '打开文件失败', icon: 'none' });
      console.error('打开失败:', err);
    }
  });
}

3.2 H5 端实现(替代方案:a 标签 + 原生下载)​

由于 H5 不支持 uni.saveFile,且 uni.downloadFile 无法获取本地路径,需通过浏览器原生 a 标签触发下载:​

/**
 * H5 下载文件
 * @param {String} url - 下载地址
 * @param {String} fileName - 自定义文件名
 */
h5Download(url, fileName = '文件') {
  // 处理跨域:若 URL 跨域,需后端配置 CORS 或使用代理
  const link = document.createElement('a');
  
  // 若需携带 Token,拼接在 URL 或通过 header(需后端支持)
  // url = `${url}?token=${uni.getStorageSync('token')}`;
  
  link.href = url;
  link.download = fileName; // 自定义下载文件名(浏览器支持有限,部分格式可能失效)
  link.target = '_blank'; // 新标签页打开(避免阻塞当前页面)
  
  // 触发点击下载
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link); // 下载后移除标签
  
  // 提示用户(H5 无法判断是否下载成功,仅提示触发)
  uni.showToast({ title: '下载已触发,请在浏览器中确认', icon: 'none' });
}

场景 2:兼容两端的统一调用方案(条件编译)​

通过 Uniapp 条件编译,让代码自动适配 H5 和小程序,无需手动判断环境:​

/**
 * 跨端下载文件(统一调用入口)
 * @param {String} url - 下载地址
 * @param {String} fileName - 自定义文件名
 */
crossDownload(url, fileName = '文件') {
  // #ifdef H5
  this.h5Download(url, fileName);
  // #endif

  // #ifdef MP
  this.miniProgramDownload(url, fileName);
  // #endif
}

模板中调用:​

<template>
  <button @click="crossDownload('https://example.***/file.pdf', '报表.pdf')">
    下载文件(兼容 H5/小程序)
  </button>
</template>

场景 3:H5 大文件下载(带进度条)​

H5 中 a 标签无法监听进度,需通过 XMLHttpRequest 手动实现:​

/**
 * H5 大文件下载(带进度监听)
 * @param {String} url - 下载地址
 * @param {String} fileName - 自定义文件名
 */
h5LargeFileDownload(url, fileName = '文件') {
  uni.showLoading({ title: '下载中...' });

  const xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'blob'; // 响应类型为二进制流

  // 监听进度
  xhr.onprogress = (e) => {
    if (e.length***putable) {
      const progress = Math.round((e.loaded / e.total) * 100);
      console.log(`下载进度:${progress}%`);
      // 实时更新进度条(如:this.downloadProgress = progress)
    }
  };

  // 下载完成
  xhr.onload = function () {
    uni.hideLoading();
    if (xhr.status === 200) {
      // 转换 blob 为下载链接
      const blob = new Blob([xhr.response]);
      const url = URL.createObjectURL(blob);

      const link = document.createElement('a');
      link.href = url;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();

      // 释放 URL 对象,避免内存泄漏
      URL.revokeObjectURL(url);
      document.body.removeChild(link);

      uni.showToast({ title: '下载成功', icon: 'su***ess' });
    } else {
      uni.showToast({ title: `下载失败:${xhr.status}`, icon: 'none' });
    }
  };

  // 下载失败
  xhr.onerror = function () {
    uni.hideLoading();
    uni.showToast({ title: '下载失败', icon: 'none' });
  };

  xhr.send();
}

四、避坑指南(关键注意点)​

  1. 小程序合法域名:​
  • 必须配置下载地址的域名(https 协议),否则报错 downloadFile:fail url not in domain list。​
  • 本地开发时,可在微信开发者工具中勾选「不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书」(仅开发环境)。​
  1. H5 跨域问题:​
  • 若下载地址与 H5 域名不同,后端必须配置 CORS 响应头,否则会出现 A***ess-Control-Allow-Origin 错误。​
  • 解决方案:后端配置 CORS 或使用 Nginx 代理转发下载请求。​
  1. 文件命名兼容性:​
  • H5 中 a 标签的 download 属性对部分格式(如 .apk、.exe)可能失效,建议后端在响应头中设置文件名(Content-Disposition: attachment; filename="文件.pdf")。​
  1. 临时文件清理:​
  • 小程序的 tempFilePath 会在退出后清理,重要文件务必通过 uni.saveFile 保存为永久路径。​
  • 可通过 uni.getSavedFileList() 查询已保存的文件,uni.removeSavedFile() 删除无用文件。​
  1. H5 进度监听:​
  • 仅 XMLHttpRequest 支持进度监听,a 标签无法实现,大文件下载建议使用 XMLHttpRequest 方案。​

五、总结​

Uniapp 跨端下载的核心是「适配环境差异」:​

  • 小程序:利用 uni.downloadFile + uni.saveFile 实现完整的下载 - 保存 - 打开流程,支持进度监听和本地存储。​
  • H5:依赖浏览器原生能力(a 标签 /XMLHttpRequest),需处理跨域和进度监听的兼容性问题。​

通过条件编译封装统一调用入口,可大幅减少冗余代码,实现「一套代码,两端运行」。实际开发中,需根据文件大小、格式和业务需求选择合适的方案,同时注意跨域、域名配置等细节,避免踩坑。

转载请说明出处内容投诉
CSS教程网 » uniapp下载文件--支持H5和小程序

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买