实时读取页面查询的数据并导出生成excel文档到本地或者服务器,进行下载
第一:excel表头实体类
package service.model.req;
import lombok.Data;
import net.sf.oval.constraint.NotBlank;
import java.io.Serializable;
import java.util.LinkedHashMap;
/**
* 渠道记录清单下载:数据映射入参类(实体表头类)
*
* @author zhangkuan
* @version Id: ChannelInfoFileDownloadReqDTO.java, v 0.1 2022-08-01 16:55 zhangkuan Exp $$
*/
@Data
public class ChannelInfoFileDownloadReqDTO implements Serializable {
private static final long serialVersionUID = 2610674654507111569L;
/**
* 渠道编码
*/
@NotBlank(message = "渠道编码")
private String channelCode;
/**
* 渠道名称
*/
@NotBlank(message = "渠道名称")
private String channelName;
/**
* 流水ID
*/
@NotBlank(message = "流水ID")
private String journalId;
/**
* 渠道结果
*/
@NotBlank(message = "渠道结果")
private String channelResult;
/**
* 错误码
*/
private String errorCode;
/**
* 错误描述
*/
private String errorMsg;
/**
* 原始错误码
*/
private String primaryErrorCode;
/**
* 原始错误描述
*/
private String primaryErrorMsg;
/**
* IP地址
*/
private String ipAddress;
/**
* 请求响应耗时毫秒
*/
private String responseTime;
/**
* 创建时间
*/
private String createdAt;
/**
* 创建人
*/
private String createdBy;
/**
* 修改时间
*/
private String updatedAt;
/**
* 修改人
*/
private String updatedBy;
/**
* 主键id
*/
private String id;
/**
* 设置表头
*
* @return LinkedHashMap<String,String>
*/
public LinkedHashMap<String,String> getLinkedHashMap() {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("channelCode","渠道编码");
map.put("channelName","渠道名称");
map.put("journalId","流水ID");
map.put("channelResult","渠道结果");
map.put("errorCode","错误码");
map.put("errorMsg","错误描述");
map.put("primaryErrorCode","原始错误码");
map.put("primaryErrorMsg","原始错误描述");
map.put("ipAddress","IP地址");
map.put("responseTime","请求响应耗时毫秒");
map.put("createdAt","创建时间");
map.put("createdBy","创建人");
map.put("updatedAt","修改时间");
map.put("updatedBy","修改人");
map.put("id","主键id");
return map;
}
}
第二:将查询出来的list数据放入表格,并给前端返回base64的串串
package service.system;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.bestpay.dubbo.result.Result;
import common.enums.system.SystemCertifyErrorCodeEnum;
import common.exception.ServiceException;
import common.utils.Base64Util;
import common.utils.StringUtil;
import service.api.system.ChannelInfoListDownloadService;
import service.api.system.ChannelInfoService;
import service.model.base.PageResDTO;
import service.model.req.ChannelInfoFileDownloadReqDTO;
import service.model.req.ChannelInfoReqDTO;
import service.model.res.ChannelInfoResDTO;
import lombok.extern.log4j.Log4j2;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 渠道记录查询 文件清单下载service
*
* @author zhangkuankuan
* @version Id: ChannelInfoListDownloadServiceImpl.java, v 0.1 2022-5-17 14:11 zhangkuankuan Exp $$
*/
@Log4j2
@DubboService
@Component
public class ChannelInfoListDownloadServiceImpl implements ChannelInfoListDownloadService {
/**
* 流水/渠道记录下载页面的上限数目
*/
@Value("${journal.downloadPageTotal}")
private int downloadPageTotal;
@Autowired
ChannelInfoService channelInfoService;
/**
* 查询出来的页面的list数据
*
* @param dtoList 查询出来的页面的list数据
* @return Result<String> base64的串串
*/
@Override
public Result<String> channelInfoListDownload(ChannelInfoReqDTO reqDTO) {
Result<PageResDTO<ChannelInfoResDTO>> result = channelInfoService.queryChannelInfoPageTotal(reqDTO);
List<ChannelInfoResDTO> dtoList = null;
if (null != result) {
dtoList = result.getResult().getResultList();
//当页面查询结果超出上限,不进行统计
if (dtoList.size() > downloadPageTotal) {
log.error("下载页面结果超出上限,不进行统计");
throw new ServiceException(SystemCertifyErrorCodeEnum.ERROR_CODE_100001.getCode(),
SystemCertifyErrorCodeEnum.DOWNLOAD_PAGE_SIZE_EXCEED_FIFTY_THOUSAND.getDesc());
}
}
//返回base64给前端
return getStringResult(dtoList);
}
/**
* 将查询出来的list数据放入表格,并给前端返回base64的串串
*
* @param dtoList 查询出来的页面的list数据
* @return Result<String> base64的串串
*/
private Result<String> getStringResult( List<ChannelInfoResDTO> dtoList) {
Result<String> result = new Result<>();
ExcelWriter writer = ExcelUtil.getWriter();
//表头类定义字段顺序与数据list保持一致
ChannelInfoFileDownloadReqDTO fileDownloadReqDTO = new ChannelInfoFileDownloadReqDTO();
LinkedHashMap<String, String> titleMap = fileDownloadReqDTO.getLinkedHashMap();
String path = Objects.requireNonNull(ExcelUtil.class.getResource("/")).getPath();//服务器、浏览器下载生成excel路径
// String path ="D:\\";//本地下载生成excel路径
File sendFile = new File(path + System.currentTimeMillis() +".xls");
try {
if (!sendFile.exists()) {
sendFile.createNewFile();
}
log.info("getFile sendFile path:{},sendFile exists():{}", sendFile.getPath(), sendFile.exists());
OutputStream outputStream = new FileOutputStream(sendFile);
//设置导出excel的请求头
setDownHeader(writer,titleMap);
writer.write(dtoList, true);
writer.flush(outputStream);
result.setResult(Base64Util.file2String(sendFile));
log.info("base64 {}",result);
} catch (Exception e) {
log.info("生成临时文件异常:e:[{}]",e.getMessage(),e);
} finally {
//删除临时文件
boolean delete = sendFile.delete();
log.info("临时文件 删除:{}", delete);
}
//返回结果
return result;
}
/**
* 设置表头
* @param writer writer
* @param titleMap titleMap
*/
private void setDownHeader(ExcelWriter writer, LinkedHashMap<String,String> titleMap) {
for(Map.Entry<String, String> entry : titleMap.entrySet()) {
if(!StringUtil.isEmpty(entry.getKey())) {
writer.addHeaderAlias(entry.getKey(),entry.getValue());
}
}
}
}
第三步:前端页面转换base64码,为excel文件
<!--新增失败原因统计 结束位置-->
<!--清单下载 开始位置-->
var fileDownLoad = function(param) {
var url = "/unity-certify/service/channelInfoListDownloadService/channelInfoListDownload.do";
//发送请求获取数据
$.ajax({
url: WWWROOT + url+"?"+param,
type:"get",
success: function(data){
//console.log(data.result.result);
//查询结果
if(data.success == false) {
alert('查询结果条数过多,导致大总管调用远程异常(建议查询控制在20000条左右)');
} else {
savePicture(data.result.result);
}
},
error: function(data){
//失败
bootbox.alert(data.errorMsg);
}
});
};
// base64转文件
function savePicture(base64) {
var bytes = atob(base64);
let ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
var blob = new Blob([ab], { type: 'application/vnd.ms-excel' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = "渠道记录查询" + ".xls";
a.click();
}
<!--清单下载 结束位置-->
第四步:测试验证
public void queryChannelInfoPage() throws ParseException {
ChannelInfoReqDTO channelInfoReqDTO = new ChannelInfoReqDTO();
channelInfoReqDTO.setOperateUser("张三");
channelInfoReqDTO.setRequestSystem("unity-certify");
channelInfoReqDTO.setTraceLogId(UUID.randomUUID().toString().replace("-", ""));;
channelInfoReqDTO.setChannelCode("OCR_ID");
//如果不传时间,默认时间是当天 "2022-05-26 00:00:00" ~ "2022-05-26 23:59:59"
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date begintime = simpleDateFormat.parse("2022-08-04 00:00:24");
Date endtime = simpleDateFormat.parse("2022-08-04 02:05:24");
channelInfoReqDTO.setBeginTime(begintime);
channelInfoReqDTO.setEndTime(endtime);
//场景1:验证界面清单下载功能,目前路径是写死的,所以点击按钮会直接在桌面新建channelFileDownload.xlsx文件,
// 并且第二次下载的数据会直接将文件里面第一次下载的数据进行覆盖
channelInfoListDownloadService.channelInfoListDownload(channelInfoReqDTO);
}

浙公网安备 33010602011771号