private static Interger ROW_SIZE = 10000;
private static interger ROW_PAGE = 10;
* divide into sheets with 10W data per sheet
int sheetCount = (rowCount/ (ROW_SIZE*ROW_PAGE))+1;
for(int i=0;i threadExecutor.submit(()->{sheetWrite()});
2)sheet写入多线程,最后一个文件写入线程的最后一个sheet写入线程可能不足1W条数据;
// 单sheet页写入数
int sheetThreadCount = rowCount - (i+1)*(ROW_SIZE*ROW_PAGE) > 0 ? ROW_PAGE : (rowCount - i*(ROW_SIZE*ROW_PAGE))/ROW_SIZE+1;
CountDownLatch threadSignal = new CountDownLatch(sheetThreadCount);
for(int j=0;j threadExecutor.submit(()->{excelWriter()});
threadSignal.await();
3)异步写入sheet文件,不同的文件写入线程写入不同的文件,所以只需要保证同一个文件写入线程下不同sheet写入线程的excelWriter异步即可;
// 获取数据
// todo
// 数据格式处理
Synchronized(excelWriter){
WriteSheet writeSheet = EasyExcel.writerSheet(sheetNo, "第" + (sheetNo+1) + "页数据");
excelWriter.write(lists, writeSheet);
4)压缩文件,将多个excel压缩成一个zip,最后上传至fast dfs,返回前端下载地址,使用hutool封装的ZipUtil方法;
package cn.hutool.core.util;
String[] paths = new String[10];
FileInputStream[] ins = new FileInputStream[10];
ZipUtil.zip(OutputStream out, String[] paths, InputStream[] ins);
byte[] bytes = outputStream.toByteArray();
// 上传文件到FastDFS 返回上传路径
String path = fastWrApper.uploadFile(bytes, bytes.length, "zip");
return path + "?filename=" + fileName;
缓存
每次请求是生成一个文件并上传至FastDFS服务器上,然后将下载路径返回给前端,有时多个用户频繁下载同一个文件(或者用户短时间内点击同一个下载任务) 。针对以上情况,考虑采用缓存,将第一次的数据缓存下来 。另外,更多java面试资料,公众号Java精选,回复java面试,获取面试资料,支持在线刷题 。
① 请求参数较多,需要根据参数判断是否为同一个下载文件请求;
- 数据集ID
- 过滤器
- 数据量
- 数据集字段(先根据ID排序,再进行拼接)
③ 当请求下载的为同一份文件时,只是文件名不同时,依旧采用同一份缓存数据;
注:针对于数据一致性的问题,不对单个数据的内容变更进行考虑,原因是大数据量下,数据是否有变更的判断较为复杂,不现实 。这里只判断在相同的请求条件下的总条数 。可行性验证
1)单个文件写入下,176个字段,14140条数据,excel大小15M,响应时间为14.66s(未报错,未触发异常)

文章插图
2)单个文件写入下,14个字段,98万数据,excel大小为96M,响应时间为42.41s(未报错,未触发异常)

文章插图
3)拆分微服务下,14个字段,98万数据,zip大小为104M,平均响应时间为27.34s(未报错,未触发异常)

文章插图
代码
文件导出核心代码
TableExport.java
public String exportTable(ExportTable exportTable) throws Exception {
StringBuffer path = new StringBuffer();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
StringBuffer sign = new StringBuffer ();
//redis key
sign.append(exportTable.getId());
try {
// 用来记录需要为 行 列设置样式
Map>>> map = new HashMap<>();
sign.append("#").append(String.join(",", fields.stream().map(e-> e.isShow()?"true":"false").collect(Collectors.toList())));
setFontStyle(0, 0, exportTable.getFields(), map);
// 获取表头长度
int headRow = head.stream().max(Comparator.comparingInt(List::size)).get().size();// 数据量超过十万 则不带样式
// 只处理表头:表头合并 表头隐藏 表头冻结
if(rowCount*fields.size() > ROW_SIZE*6.4){
map.put("cellStyle", null);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 海运dhc是什么费用……dhc公铁好用吗?
- 免洗发膜哪个牌子好用 什么发膜好用
- 竞价点击器哪个好用。请问百度竞价点击器在哪里能找到
- 最好用的电脑手写板 手写板软件
- 鱼子酱发膜真的有用吗?十大最好用发膜排行榜?
- 好用的润唇膏 小蜜缇润唇膏
- 露华浓洗发水好用吗 露华浓生姜
- 花印怎么样好用吗 花印怎么样
- BT搜索蜘蛛 bt磁力搜索
- 娇韵诗哪个水好用 娇韵诗防晒霜
