Browse Source

【报表】pc工作单报表批量下载-优化导出的文件名称

dev
wangxianzhang 3 years ago
parent
commit
47568e5f5d
  1. 17
      epmet-commons/epmet-commons-feignclient/src/main/java/com/epmet/commons/feignclient/dtos/result/JiMuReportBriefResultDTO.java
  2. 8
      epmet-commons/epmet-commons-feignclient/src/main/java/com/epmet/commons/feignclient/feigns/JiMuReportOpenFeignClient.java
  3. 7
      epmet-commons/epmet-commons-feignclient/src/main/java/com/epmet/commons/feignclient/feigns/fallback/JiMuReportOpenFeignClientFallback.java
  4. 77
      epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/service/impl/IcCustomerReportServiceImpl.java

17
epmet-commons/epmet-commons-feignclient/src/main/java/com/epmet/commons/feignclient/dtos/result/JiMuReportBriefResultDTO.java

@ -0,0 +1,17 @@
package com.epmet.commons.feignclient.dtos.result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 报表简要信息result dto
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JiMuReportBriefResultDTO {
private String id;
private String code;
private String name;
}

8
epmet-commons/epmet-commons-feignclient/src/main/java/com/epmet/commons/feignclient/feigns/JiMuReportOpenFeignClient.java

@ -3,6 +3,7 @@ package com.epmet.commons.feignclient.feigns;
import com.epmet.commons.feignclient.dtos.JiMuPage; import com.epmet.commons.feignclient.dtos.JiMuPage;
import com.epmet.commons.feignclient.dtos.JiMuResult; import com.epmet.commons.feignclient.dtos.JiMuResult;
import com.epmet.commons.feignclient.dtos.form.JimuReportExportRequestDTO; import com.epmet.commons.feignclient.dtos.form.JimuReportExportRequestDTO;
import com.epmet.commons.feignclient.dtos.result.JiMuReportBriefResultDTO;
import com.epmet.commons.feignclient.dtos.result.JiMuReportDetailResultDTO; import com.epmet.commons.feignclient.dtos.result.JiMuReportDetailResultDTO;
import com.epmet.commons.feignclient.dtos.result.JimuReportDbDataResultDTO; import com.epmet.commons.feignclient.dtos.result.JimuReportDbDataResultDTO;
import com.epmet.commons.feignclient.dtos.result.JimuReportFieldTreeResultDTO; import com.epmet.commons.feignclient.dtos.result.JimuReportFieldTreeResultDTO;
@ -44,4 +45,11 @@ public interface JiMuReportOpenFeignClient {
@PostMapping("jmreport/exportAllExcelStream") @PostMapping("jmreport/exportAllExcelStream")
Response exportAllExcelStream(JimuReportExportRequestDTO param); Response exportAllExcelStream(JimuReportExportRequestDTO param);
/**
* 报表简要信息
* @return
*/
@GetMapping("jmreport/get/{report-id}")
JiMuResult<JiMuReportBriefResultDTO> getReportBrief(@PathVariable("report-id") String reportId);
} }

7
epmet-commons/epmet-commons-feignclient/src/main/java/com/epmet/commons/feignclient/feigns/fallback/JiMuReportOpenFeignClientFallback.java

@ -3,6 +3,7 @@ package com.epmet.commons.feignclient.feigns.fallback;
import com.epmet.commons.feignclient.dtos.JiMuPage; import com.epmet.commons.feignclient.dtos.JiMuPage;
import com.epmet.commons.feignclient.dtos.JiMuResult; import com.epmet.commons.feignclient.dtos.JiMuResult;
import com.epmet.commons.feignclient.dtos.form.JimuReportExportRequestDTO; import com.epmet.commons.feignclient.dtos.form.JimuReportExportRequestDTO;
import com.epmet.commons.feignclient.dtos.result.JiMuReportBriefResultDTO;
import com.epmet.commons.feignclient.dtos.result.JiMuReportDetailResultDTO; import com.epmet.commons.feignclient.dtos.result.JiMuReportDetailResultDTO;
import com.epmet.commons.feignclient.dtos.result.JimuReportDbDataResultDTO; import com.epmet.commons.feignclient.dtos.result.JimuReportDbDataResultDTO;
import com.epmet.commons.feignclient.dtos.result.JimuReportFieldTreeResultDTO; import com.epmet.commons.feignclient.dtos.result.JimuReportFieldTreeResultDTO;
@ -48,4 +49,10 @@ public class JiMuReportOpenFeignClientFallback implements JiMuReportOpenFeignCli
JiMuResult rst = new JiMuResult<>(false, "请求失败", 200, null,null); JiMuResult rst = new JiMuResult<>(false, "请求失败", 200, null,null);
return rst; return rst;
} }
@Override
public JiMuResult<JiMuReportBriefResultDTO> getReportBrief(String reportID) {
JiMuResult rst = new JiMuResult<>(false, "请求失败", 200, null,null);
return rst;
}
} }

77
epmet-module/oper-customize/oper-customize-server/src/main/java/com/epmet/service/impl/IcCustomerReportServiceImpl.java

@ -9,10 +9,7 @@ import com.epmet.commons.feignclient.dtos.JiMuPage;
import com.epmet.commons.feignclient.dtos.JiMuResult; import com.epmet.commons.feignclient.dtos.JiMuResult;
import com.epmet.commons.feignclient.dtos.form.JiMuReportFormDTO; import com.epmet.commons.feignclient.dtos.form.JiMuReportFormDTO;
import com.epmet.commons.feignclient.dtos.form.JimuReportExportRequestDTO; import com.epmet.commons.feignclient.dtos.form.JimuReportExportRequestDTO;
import com.epmet.commons.feignclient.dtos.result.JiMuReportDetailResultDTO; import com.epmet.commons.feignclient.dtos.result.*;
import com.epmet.commons.feignclient.dtos.result.JiMuReportResultDTO;
import com.epmet.commons.feignclient.dtos.result.JimuReportDbDataResultDTO;
import com.epmet.commons.feignclient.dtos.result.JimuReportFieldTreeResultDTO;
import com.epmet.commons.feignclient.feigns.JiMuReportOpenFeignClient; import com.epmet.commons.feignclient.feigns.JiMuReportOpenFeignClient;
import com.epmet.commons.mybatis.service.impl.BaseServiceImpl; import com.epmet.commons.mybatis.service.impl.BaseServiceImpl;
import com.epmet.commons.tools.constant.*; import com.epmet.commons.tools.constant.*;
@ -280,14 +277,18 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
// 1. 首先去积木服务,查询出报表数据源的详细信息,包括报表url,isList;获取到哪一列是id(idFieldName) // 1. 首先去积木服务,查询出报表数据源的详细信息,包括报表url,isList;获取到哪一列是id(idFieldName)
// 根据报表id查询数据源列表,取出第一个 // 查询报表的字段列表(含数据源列表)
JiMuResult<List<List<JimuReportFieldTreeResultDTO>>> fResult = jiMuReportOpenFeignClient.fieldTree(reportId); JiMuResult<List<List<JimuReportFieldTreeResultDTO>>> fResult = jiMuReportOpenFeignClient.fieldTree(reportId);
String datasourceId = fResult.getResult().get(0).get(0).getDbId(); String datasourceId = fResult.getResult().get(0).get(0).getDbId();
// 根据数据源ID查询数据源信息 // 报表数据源信息
JiMuResult<JimuReportDbDataResultDTO> dbData = jiMuReportOpenFeignClient.loadDbData(datasourceId); JiMuResult<JimuReportDbDataResultDTO> dbData = jiMuReportOpenFeignClient.loadDbData(datasourceId);
JimuReportDbDataResultDTO.ReportDB reportDb = dbData.getResult().getReportDb(); JimuReportDbDataResultDTO.ReportDB reportDb = dbData.getResult().getReportDb();
// 报表简要信息
JiMuResult<JiMuReportBriefResultDTO> reportBriefResult = jiMuReportOpenFeignClient.getReportBrief(reportId);
JiMuReportBriefResultDTO reportBrief = reportBriefResult.getResult();
// api的url // api的url
String apiUrl = reportDb.getApiUrl(); String apiUrl = reportDb.getApiUrl();
// api方法 // api方法
@ -296,29 +297,34 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
//String isList = reportDb.getIsList(); //String isList = reportDb.getIsList();
// 返回的列表中,哪个字段是ID // 返回的列表中,哪个字段是ID
String idFieldName = null; String idFieldName = null;
String nameFieldName = null;
boolean isHttps = false; boolean isHttps = false;
Matcher matcher = Pattern.compile("(http://|https://).+idFieldName=(\\w+).*").matcher(apiUrl); Matcher matcher = Pattern.compile("(http://|https://).+idFieldName=(\\w+).+nameFieldName=(\\w+).*").matcher(apiUrl);
if (matcher.matches()) { if (matcher.matches()) {
String proto = matcher.group(1); String proto = matcher.group(1);
if ("https://".equals(proto)) { if ("https://".equals(proto)) {
isHttps = true; isHttps = true;
} }
idFieldName = matcher.group(2); idFieldName = matcher.group(2);
nameFieldName = matcher.group(3);
} }
if (StringUtils.isBlank(idFieldName)) { if (StringUtils.isBlank(idFieldName)) {
throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode(), "配置的业务api url缺少idFieldName列"); throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode(), "配置的业务api url缺少idFieldName列");
} }
if (StringUtils.isBlank(idFieldName)) {
throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode(), "配置的业务api url缺少nameFieldName列");
}
// 2. 调用该url的接口,获取到一个列表,根据idFieldName取出ID列 // 2. 调用该url的接口,获取到一个列表,根据idFieldName取出ID列
List<String> ids = listIds(bizId, paramKey, apiUrl, isHttps, idFieldName); HashMap<String, String> idAndNames = listBizObjectIdAndName(bizId, paramKey, apiUrl, isHttps, idFieldName, nameFieldName);
// 3. 然后以这一列作为查询条件,循环,继续调用该接口,得到单条数据,每一条数据都下载一个excel,最后将其打包为一个压缩包下载 // 3. 然后以这一列作为查询条件,循环,继续调用该接口,得到单条数据,每一条数据都下载一个excel,最后将其打包为一个压缩包下载
Path storePath = makeTemporaryDownloadDir(reportId); Path storePath = makeTemporaryDownloadDir(reportId);
// 4.生成压缩文件 // 4.生成压缩文件
Path zipFile = downloadAndComppress(storePath, reportId, reportDb.getDbChName(), paramKey, ids); Path zipFile = downloadAndComppress(storePath, reportId, reportBrief.getName(), paramKey, idAndNames);
// 5.下载 // 5.下载
try (FileInputStream fis = new FileInputStream(zipFile.toFile())) { try (FileInputStream fis = new FileInputStream(zipFile.toFile())) {
@ -342,10 +348,9 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
/** /**
* 批量下载 * 批量下载
* @param storePath 本次导出文件的存储路径子目录包括zip文件时间戳命名的子目录用于存放临时excel(导出完成会删掉) * @param storePath 本次导出文件的存储路径子目录包括zip文件时间戳命名的子目录用于存放临时excel(导出完成会删掉)
* @param ids
* @return 压缩文件路径 * @return 压缩文件路径
*/ */
private Path downloadAndComppress(Path storePath, String reportId, String reportName, String paramKey, List<String> ids) { private Path downloadAndComppress(Path storePath, String reportId, String reportName, String paramKey, HashMap<String, String> idAndNames) {
// 请求头 // 请求头
Map<String, Object> headers = new HashMap<>(); Map<String, Object> headers = new HashMap<>();
headers.put(Constant.AUTHORIZATION_HEADER, EpmetRequestHolder.getHeader(Constant.AUTHORIZATION_HEADER)); headers.put(Constant.AUTHORIZATION_HEADER, EpmetRequestHolder.getHeader(Constant.AUTHORIZATION_HEADER));
@ -360,7 +365,7 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
param.getQueryParam().setParamKey(paramKey); param.getQueryParam().setParamKey(paramKey);
param.getQueryParam().setToken(EpmetRequestHolder.getLoginUserAuthorizationToken()); param.getQueryParam().setToken(EpmetRequestHolder.getLoginUserAuthorizationToken());
ArrayList<File> files = new ArrayList<>(); HashMap<String, File> files = new HashMap<>();
String currentTimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")); String currentTimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
@ -373,13 +378,15 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
} }
// 将所有id分片,交给多个线程并行处理 // 将所有id分片,交给多个线程并行处理
List<List<String>> idParts = ListUtils.partition(ids, 100); ArrayList<String> idList = new ArrayList<>();
idList.addAll(idAndNames.keySet());
List<List<String>> idParts = ListUtils.partition(idList, 100);
// 1. 循环下载所有id对应的excel // 1. 循环下载所有id对应的excel
CountDownLatch cdl = new CountDownLatch(idParts.size()); CountDownLatch cdl = new CountDownLatch(idParts.size());
for (List<String> idPart : idParts) { for (List<String> idPart : idParts) {
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
downloadXlsByBatchByBizId(reportId, idPart, param, xlsxStorePath, files, cdl); downloadXlsByBatchByBizId(reportId, idPart, idAndNames, param, xlsxStorePath, files, cdl);
}, executorService); }, executorService);
} }
@ -397,9 +404,17 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
final ZipOutputStream zos = new ZipOutputStream(fos)) { final ZipOutputStream zos = new ZipOutputStream(fos)) {
// 循环每一个文件 // 循环每一个文件
for (File file : files) { HashMap<String, Integer> bizObjNameAndCount = new HashMap<>(32);
for (Map.Entry<String, File> entry : files.entrySet()) {
String bizObjectId = entry.getKey();
File file = entry.getValue();
String bizObjName = idAndNames.get(bizObjectId);
bizObjName = getBizObjName(bizObjNameAndCount, bizObjName);
try (final FileInputStream fis = new FileInputStream(file.getAbsolutePath())) { try (final FileInputStream fis = new FileInputStream(file.getAbsolutePath())) {
zos.putNextEntry(new ZipEntry(reportName + "_" + currentTimeStr + "/" + file.getName())); zos.putNextEntry(new ZipEntry(String.format("%s_%s/%s_%s.xlsx", reportName, currentTimeStr, reportName, bizObjName)));
final byte[] buffer = new byte[10240]; final byte[] buffer = new byte[10240];
for (int len; (len = fis.read(buffer)) > 0; ) { for (int len; (len = fis.read(buffer)) > 0; ) {
zos.write(buffer, 0, len); zos.write(buffer, 0, len);
@ -421,6 +436,22 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
return zipFile; return zipFile;
} }
public String getBizObjName(HashMap<String, Integer> bizObjNameAndCount, String bizObjName) {
Integer nameCount = bizObjNameAndCount.get(bizObjName);
if (nameCount == null) {
nameCount = 1;
bizObjNameAndCount.put(bizObjName, nameCount);
} else {
bizObjNameAndCount.put(bizObjName, ++nameCount);
}
if (nameCount > 1) {
bizObjName = String.format("%s(%d)", bizObjName, nameCount);
}
return bizObjName;
}
/** /**
* 批量下载xlsx * 批量下载xlsx
* @param reportId * @param reportId
@ -429,7 +460,7 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
* @param xlsxStorePath * @param xlsxStorePath
* @param files * @param files
*/ */
public void downloadXlsByBatchByBizId(String reportId, List<String> bizIds, JimuReportExportRequestDTO param, Path xlsxStorePath, ArrayList<File> files, public void downloadXlsByBatchByBizId(String reportId, List<String> bizIds, Map<String, String> idAndNames, JimuReportExportRequestDTO param, Path xlsxStorePath, Map<String, File> files,
CountDownLatch cdl) { CountDownLatch cdl) {
for (String id : bizIds) { for (String id : bizIds) {
@ -456,7 +487,7 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
final File excelFile = xlsxStorePath.resolve("file_" + id + matcher.group(2)).toFile(); final File excelFile = xlsxStorePath.resolve("file_" + id + matcher.group(2)).toFile();
files.add(excelFile); files.put(id, excelFile);
try (FileOutputStream fos = new FileOutputStream(excelFile)) { try (FileOutputStream fos = new FileOutputStream(excelFile)) {
IOUtils.copy(response.body().asInputStream(), fos); IOUtils.copy(response.body().asInputStream(), fos);
} catch (Exception e) { } catch (Exception e) {
@ -514,7 +545,7 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
* @param idFieldName * @param idFieldName
* @return * @return
*/ */
public List<String> listIds(String id, String paramKey, String apiUrl, boolean isHttps, String idFieldName) { public HashMap<String, String> listBizObjectIdAndName(String id, String paramKey, String apiUrl, boolean isHttps, String idFieldName, String nameFieldName) {
apiUrl = apiUrl.replace("'${id}'", id == null ? "" : id); apiUrl = apiUrl.replace("'${id}'", id == null ? "" : id);
apiUrl = apiUrl.replace("'${paramKey}'", paramKey); apiUrl = apiUrl.replace("'${paramKey}'", paramKey);
@ -526,7 +557,7 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
Object data = dataJsonObject.get("data"); Object data = dataJsonObject.get("data");
JSONArray array = new JSONArray(); JSONArray array = new JSONArray();
ArrayList<String> ids = new ArrayList<>(); HashMap<String, String> idAndNames = new HashMap<>();
if (data instanceof JSONObject) { if (data instanceof JSONObject) {
// 这种可能是pageData的 // 这种可能是pageData的
@ -539,8 +570,10 @@ public class IcCustomerReportServiceImpl extends BaseServiceImpl<IcCustomerRepor
for (ListIterator<Object> it = array.listIterator(); it.hasNext(); ) { for (ListIterator<Object> it = array.listIterator(); it.hasNext(); ) {
JSONObject e = (JSONObject) it.next(); JSONObject e = (JSONObject) it.next();
ids.add(e.getString(idFieldName)); String idValue = e.getString(idFieldName);
String nameValue = e.getString(nameFieldName);
idAndNames.put(idValue, nameValue);
} }
return ids; return idAndNames;
} }
} }
Loading…
Cancel
Save