美文网首页
2022-12-06 uniApp H5端实现下载文件(包含微信

2022-12-06 uniApp H5端实现下载文件(包含微信

作者: Cjate | 来源:发表于2022-12-06 14:24 被阅读0次

    功能需求背景:

    项目开发中的需求,需在移动H5实现明细等列表导出下载功能,又因项目用户大多运行于微信内浏览器,而微信浏览器禁止下载行为,需引导用户跳转第三方浏览器完成下载。

    功能实现思路:

    1. 前端发送导出请求
    2. 后端根据请求条件筛选数据生成CSV文件
    3. 后端提供"导出记录列表"接口,给到前端生成成功或失败状态以及下载地址
    4. 前端根据用户运行环境(微信内浏览器或者外部浏览器),引导用户完成报表下载
    流程图
    文件下载流程.png

    使用技术栈

    uniApp(vue2) + uview(1.X版本)
    (本文主要讲解功能实现,页面样式表不另外提供哈)

    目录结构如下

    image.png

    实现代码

    公共函数

    // 本人项目中,已注入Vue原型链的$m,故下方代码通过this.$m.isWxBrowser()与this.$m.isIos()调用
    export const isWxBrowser = () => {
      // 判断是否H5微信环境,true为微信浏览器
     const ua = navigator.userAgent.toLowerCase()
     return ua.match(/MicroMessenger/i) == 'micromessenger' ? true : false
    }
    
    export const isIos = ()=> {
      // 是否IOS true为ios
      let u = navigator.userAgent
      let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
      return isIOS ? true : false
    }
    

    页面 pages.json 配置

    "subPackages": [
        {
          "root": "pagesA",
          "pages": [
            {
              "path": "upLoad/exportLists",
              "style": {
                "navigationBarTitleText": "导出记录",
                "enablePullDownRefresh": true
              }
            },
            {
              "path": "upLoad/uploadFile",
              "style": {
                "navigationBarTitleText": "下载",
              }
            }
          ]
        }
      ],
    

    pagesA/upLoad/exportLists 导出记录页面

    <template>
      <view class="page">
        <u-alert-tips show-icon type="warning" title="下拉可更新导出状态"></u-alert-tips>
        <view class="list">
          <view class="mt-10" v-for="(item, i) in lists" :key="item.id">
            <view class="list-item flex justify-between align-center">
              <view class="item-info flex-sub flex flex-column justify-between">
                <view class="time text-14">文件名:{{ item.file_name }}</view>
                <view class="time text-14">状态:{{ item.status_text }}</view>
                <view class="time text-14">创建时间:{{ item.created_at }}</view>
              </view>
              <u-button v-if="item.status == 1" style="margin: 0;" shape="square" type="error" size="mini" @click="downFile(item.url)">下载</u-button>
            </view>
          </view>
        </view>
      </view>
    </template>
    
    <script>
    import { downLoadFile } from './uploadFun';
    export default {
      name: 'exportLists',
      data() {
        return {
          lists: [
            {
              created_at: "2022-12-03 15:11:57",
              file_name: "文件下载测试",
              id: 1,
              status: 1,
              status_text: "已完成",
              url: "https://xxx.com/settlement_2022-12-03_15_11_59.csv", // 文件下载地址
            }
          ]
        };
      },
      methods: {
        downFile(url){
          if(this.$m.isWxBrowser()) {
            // 微信浏览器引导到文件下载页去
            var local = encodeURIComponent(url); // 当前H5页面的url
            this.$m.jump(`/pagesA/upLoad/uploadFile?url=${local}`) // 封装的跳转,同uni.navigateTo();
          } else {
            // 调用下载函数
            downLoadFile(url)
          }
        },
      }
    }
    </script>
    

    pagesA/upLoad/uploadFile 下载页

    <template>
      <view>
        <view class="main flex flex-column align-center justify-center">
          <template v-if="fileUrl">
            <view class="text text-center text-16 text-bold" v-if="fileName">{{ fileName }}</view>
            <u-button class="download-btn mt-30" shape="square" type="primary" @click="downFile()">下载文件</u-button>
          </template>
          <u-empty v-else text="下载地址错误" mode="data"></u-empty>
        </view>
      </view>
    </template>
    
    <script>
      import { downLoadFile } from './uploadFun';
      export default {
        name: 'downLoadFile',
        data() {
          return {
            isWx: this.$m.isWxBrowser(), // 是否微信内部浏览器
            fileUrl: '',
            fileName: ''
          };
        },
        onLoad(options) {
          if(options && options.url){
            this.fileUrl = decodeURIComponent(options.url); // 文件下载地址
            let urlArrLength = this.fileUrl.split('/').length;
            this.fileName = this.fileUrl.split('/')[urlArrLength - 1]; // 文件名
            this.wxBrowserModal();
          }
        },
        methods: {
          wxBrowserModal() {
            // 统一处理微信浏览器提示
            if(this.isWx) {
              // 此处提示可自行优化,比如遮罩层加引导图引导用户操作跳转
              uni.showModal({
                title: '提示',
                content: '请点击右上角,在浏览器打开页面下载。',
                showCancel: false
              })
            }
            return !this.isWx // 方便downFile方法使用,return false停止执行下载
          },
          downFile() {
            this.wxBrowserModal() && downLoadFile(this.fileUrl)
          }
        },
      }
    </script>
    
    <style lang="scss" scoped>
      .main {
        position: fixed;
        width: 100%;
        height:100vh;
      }
      .download-btn {
        width:50%;
      }
    </style>
    

    uploadFun.js 文件

    import { isIos } from '@/utils/util'; // 导入公共函数isIos(),代码已在上方"公共函数"提供
    // csv文件下载
    export const downLoadFile = (fileUrl)=> {
      if(isIos()) {
        // ios系统
        // 通过链接获取文件名
        let urlArrLength = fileUrl.split('/').length,
            fileName = fileUrl.split('/')[urlArrLength - 1]; // 文件名
        uni.showLoading({
          title: "正在请求数据"
        });
        uni.request({
          url: fileUrl, //获取文件流的请求路径
          responseType: "arraybuffer",
          success: (response) => {
            uni.hideLoading();
            if (!response) {
              uni.showToast({
                title: "下载失败",
                duration: 2000
              });
              return
            }
            let blob = new Blob([response.data])
            let downloadElement = document.createElement("a")
            let href = window.URL.createObjectURL(blob) //创建下载的链接
            downloadElement.href = href
            downloadElement.download = fileName //下载后文件名
            document.body.appendChild(downloadElement)
            downloadElement.click() //点击下载
            uni.showToast({
              title: "下载成功",
              duration: 2000
            })
            document.body.removeChild(downloadElement) //下载完成移除元素
            window.URL.revokeObjectURL(href) //释放掉blob对象
          }
        })
      } else {
        // 安卓系统及其他
        window.open(url)
      }
    }
    

    列表页效果图


    image.png

    下载页效果图


    下载页效果图.png
    微信内部浏览器会弹出提示
    微信内部浏览器弹出提示.png

    相关文章

      网友评论

          本文标题:2022-12-06 uniApp H5端实现下载文件(包含微信

          本文链接:https://www.haomeiwen.com/subject/adgifdtx.html