IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 超好用的Excel异步导出功能 -> 正文阅读

[JavaScript知识库]超好用的Excel异步导出功能

之前也做过关于Excel的导出案例,此次也是在其基础上进行改造升级:

https://www.bilibili.com/video/BV1kf4y1i761?p=5

但是之前的导出存在这么几个问题:

  • 如果是数据量很大容易导致页面卡死(我曾导出30w条数据,直接导致OOM)
  • 用户体验很糟糕,数据量一多就会等很久,而且用户没办法做别的事情。
  • 每次点击导出都需要走一遍完整的导出过程(这个其实还好)
  • 没办法对每次导出的数据进一个规整

今天使用异步导出来解决上述问题。


一、UML图

1-1、导出图

前台 Controller ServiceA ServiceB 点击导出 往数据库插入记录 插入一条下载记录 id name文件名 rows 下载行数 (null) takeUpTime 下载耗时 (null) downloadUrl 下载地址(null) 异步下载 (id、startTime) success 下载成功,稍等片刻去【下载中心】下载 根据需求去获取对应的数据 把数据生成一个文件保存起来 根据Id获取刚刚插入的记录 完善以下数据 rows 下载行数 takeUpTime 下载耗时 downloadUrl 下载地址(null) 前台 Controller ServiceA ServiceB

1-2、下载图

前台 Controller 获取下载列表 返回下载列表 downLoadUrl 返回文件流 前台 Controller

从上面的图中可以看出,整个下载是异步的,用户不需要在页面等待,每次导出我们都生成一个记录和一个文件,用户可以多次下载。


二、功能实现

2-1、记录实体

/**
 * Excel列表数据
 *
 * @author 小道仙97
 * @date 2021/8/8
 */
public class ExcelList {

    /**
     * id
     */
    private String id;

    /**
     * 文件名
     */
    private String name;

    /**
     * 下载行数
     */
    private Integer rows;

    /**
     * 下载耗时
     */
    private Long takeUpTime;

    /**
     * 下载地址
     */
    private String downloadUrl;
}

2-2、Controller

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * Excel导出
 *
 * @author 小道仙97
 * @date 2021-08-08
 */
@RestController
public class ExportExcelController {

    @Autowired
    private ExportExcel exportExcel;

    // 模仿下载列表
    public static List<ExcelList> list = new ArrayList<>(10);

    /**
     * Excel 导出
     * @throws Exception
     */
    @GetMapping("/excel/export")
    public void export() {
        Long startTime = System.currentTimeMillis();
        String name = "Excel异步导出测试" + UUID.randomUUID().toString() + ".xlsx";
        String id = UUID.randomUUID().toString();
        ExcelList excelList = new ExcelList();
        excelList.setId(id);
        excelList.setName(name);
        list.add(excelList);
        // 异步导出
        exportExcel.asyncExportExcel(id,name,startTime);

    }

    /**
     * 获取导出列表 - 模拟
     */
    @GetMapping("/excel/list")
    public List<ExcelList> list() {
       return list;
    }

    /**
     * 文件下载
     */
    @GetMapping("/excel/downLoad")
    public void downLoad(HttpServletResponse response,@RequestParam  String url) {
        FileUtils.download(url, response);
    }
}

2-3、异步下载实现

ExportExcel

注:使用异步注解@Async 需要先在启动类上开启 @EnableAsync

import org.springframework.scheduling.annotation.Async;

public interface ExportExcel {

    /**
     * 异步导出
     * @param id 唯一记录Id
     * @param name 文件名称
     * @param startTime 下载开始时间
     */
    @Async
    void asyncExportExcel(String id,String name,Long startTime);
}

TestExportExcelImpl

@Service
public class TestExportExcelImpl implements ExportExcel {

    @Override
    public void asyncExportExcel(String id,String name,Long startTime) {
        // 模拟查询数据过程
        String[] header = new String[]{"姓名","年纪"};
        String[] keys = new String[]{"name","age"};
        List<Map<String, Object>> content = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("name","小道仙");
        map1.put("age","23");
        content.add(map1);
        Map<String, Object> map2 = new HashMap<>();
        map2.put("name","小道仙97");
        map2.put("age","97");
        content.add(map2);

        try {
            // 获取Excel导出文件流
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ExcelUtils.exportExcel(header,keys,content,"first",os);
            byte[] content1 = os.toByteArray();
            InputStream inputStream = new ByteArrayInputStream(content1);
            // 上传文件 返回下载地址
            String url = FileUtils.uploadInputStream(inputStream, name);
            /**
             * 找到当前数据并封装结果集
             *
             * 其实这里很简单并无这么复杂,实际情况我们只需要一个 update 语句就可以搞定
             */
            for (ExcelList item : ExportExcelController.list) {
                if (item.getId().equals(id)) {
                    item.setRows(content.size());
                    item.setDownloadUrl(url);
                    item.setTakeUpTime(System.currentTimeMillis() - startTime);
                    break;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

三、演示

下面的演示的前提都是在启动了项目的基础上

3-1、导出

因为没有做任何的返回值,所以是空返回,这里也可以自定义任何提示返回。

http://127.0.0.1:8888/excel/export


3-2、下载列表

http://127.0.0.1:8888/excel/list

返回结果如下:

[
    {
        "id": "d3cb3551-cb33-445e-8e60-9534197f6647",
        "name": "Excel异步导出测试80d50264-3930-4667-8bc5-2d4a1cfe0d9d.xlsx",
        "rows": 2,
        "takeUpTime": 5,
        "downloadUrl": "2021/8/8/Excel异步导出测试80d50264-3930-4667-8bc5-2d4a1cfe0d9d.xlsx"
    }
]

3-3、下载

http://127.0.0.1:8888/excel/downLoad?url=2021/8/8/Excel异步导出测试80d50264-3930-4667-8bc5-2d4a1cfe0d9d.xlsx



视频看讲解地址:https://www.bilibili.com/video/BV1kf4y1i761

关注微信公众号回复:xdxFrameSimple 获取源码。

在这里插入图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-05 10:43:24  更:2021-09-05 10:44:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 15:20:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码