解决e.writeBook和e.WriteReportAsPDF无法在JQuery、Vue、Uniapp体系里触发下载的方案,完美实现[异步生成+异步发送],彻底杜绝文件重复写入

发表日期: 2022-03-31
文章位置: 首页 / 经验分享 / Web经验分享

1存在问题

在狐表weui教程里,直接通过Http请求,e.writeBooke.WriteReportAsPDF都是可以顺利生成excel文件下载,或者是生成pdf下载

按此在新窗口浏览图片

但是使用第三方框架时,也就是在Jquery的Ajax里、Vue的Axios里、Uniapp的Request方法里,都无法触发下载

但是在F12控制台里,能看到狐表已经做出回复,能收到服务器端发过来的数据

按此在新窗口浏览图片

按此在新窗口浏览图片
很多人以为是狐表的bug,这个生成方法只能用在weui。于是就用回传统的方法

  1. 先本地生成Excel/PDF

  2. 然后把url链接发送给前端

  3. 前端再触发下载

这种模式有2个问题

  1. 生成Excel或者专业报表的PDF时,是主线程同步的,多人用的时候,会出现性能问题。

  2. 你稍微不注意,可能会并发同时生成同名同目录文件,导致文件重复写入占用,磁盘IO写入报错。会让程序一直在写入,把cpu飙升到100%占用(我最近遇到了),更严重的会导致程序崩溃退出

image.png

狐表高开文档原文:

1、虽然WriteFile是异步执行的,但是Excel报表的生成和保存却是和主线程同步的,且Excel报表的生成并非很高效,所以用户量比较大的时候,会影响效率。

2、整个过程要分别保存和读取一次文件,我们知道计算机性能的瓶颈就是硬盘的读写,所以这同样会影响效率。

3、由于要保存为实际的文件,所以容易出现文件名冲突,假定有多个用户同时访问,上面的代码肯定会出错,虽然可以采用一些手段避免同名冲突,但毕竟增加了工作量。

所以最好的方案:还是用e.writeBooke.WriteReportAsPDF,实现【异步生成+异步发送】

2问题分析

其实不是狐表有bug,而是你没理解e.writeBook和e.WriteReportAsPDF是通过什么机制,实现了“异步生成+异步发送”

实际上,这2个方法,都是把文件,直接生成为Blob二进制格式的文件流,直接发送给浏览器,浏览器已经成功接收了,见下图

按此在新窗口浏览图片

浏览器没能触发下载,是前端代码的问题,并不是狐表的问题。需要改动一些js代码。

3解决方法

3.1狐表后端代码

HttpRequest事件代码:(非常简单,跟帮助文档一样,保持不变)
Select Case e.path
    Case "emp.xls" '下载为文件
        Dim Book As New XLS.Book(ProjectPath & "Attachments\资料卡.xls")
        book.AddDataTable("员工","数据源名称","Sel ect * from {员工} where 姓名 = '王伟'")
        e.WriteBook(book,"emp.xls",False)
End Select

3.2JQuery和Vue体系的改动

JQuery是通过Ajax异步请求,Vue是通过Axios异步请求
这些post的异步请求,收到Blob文件流的时候,需要增加指定回复的类型responseType: 'blob'
axios({
    url: 'xxxx',          // 请求路径
    method: 'post',           // 请求方式
    data: {id:  0  },       // 传给后台的参数
    responseType: 'blob', // 响应类型修改为blob(默认是json)
}).then(res => {
    console.log('请求结果:', res);
});
然后接收代码,要构造A标签进行下载
axios({
    url: 'xxxx',          // 请求路径
    method: 'post',           // 请求方式
    data: {id:  0  },       // 传给后台的参数
    responseType: 'blob', // 响应类型修改为blob(默认是json)
}).then(res => {
    //模拟a标签下载文件流
    let fileName = '报价单.xlsx' //下载的文件名
    let blob = new Blob([res]) //处理文档流
    let elink = document.createElement('a')
    elink.download = fileName
    elink.style.display = 'none'
    elink.href = URL.createObjectURL(blob)
    document.body.appendChild(elink)
    elink.click()
    URL.revokeObjectURL(elink.href) // 释放URL 对象
    document.body.removeChild(elink)
})
成功效果:
按此在新窗口浏览图片

3.3Uniapp体系的改动

Uni.Request也是类似于异步请求的东西,也是要增加responseType。只不过在Uniapp体系里,不是写blob,而是responseType: 'arraybuffer'
按此在新窗口浏览图片

uni.request({
    url: 'xxx',           // 请求路径
    method: 'POST',         // 请求方式
    data: {id: 0 },        / 传给后台的参数
    responseType: 'arraybuffer',  // 响应类型修改
})
然后接收代码,也是相同处理,进行A标签构造下载
uni.request({
    url: 'xxx',                       // 请求路径
    method: 'POST',                   // 请求方式
    data: {id: 0 },                 // 传给后台的参数
    responseType: 'arraybuffer',  // 响应类型修改
}).then(res => {
    //模拟a标签下载文件流
    let fileName = '报价单.xlsx' //下载的文件名
    let blob = new Blob([res]) //处理文档流
    let elink = document.createElement('a')
    elink.download = fileName
    elink.style.display = 'none'
    elink.href = URL.createObjectURL(blob)
    document.body.appendChild(elink)
    elink.click()
    URL.revokeObjectURL(elink.href) // 释放URL 对象
    document.body.removeChild(elink)
})
成功效果:
按此在新窗口浏览图片

4效果体验

A2迷你产品报价系统,里面的报价单模块,有带图导出Excel功能体验,可体验下这种【异步生成+异步发送】的效率

随便看看

Copyright © 2016-2022 江门蓬江区华越科技公司 版权所有 | 承接软件定制开发,欢迎联系
粤ICP备17073215号