feat: 带文件导出

This commit is contained in:
2023-09-21 10:52:26 +08:00
parent b99c16430d
commit 97adca0d50
6 changed files with 251 additions and 19 deletions
@@ -1,5 +1,6 @@
package com.jero.modules.laws.common.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -9,6 +10,7 @@ import com.jero.common.constant.enums.YesOrNoEnum;
import com.jero.common.exception.JeroBootException;
import com.jero.common.system.vo.LoginUser;
import com.jero.common.util.MessageUtils;
import com.jero.common.util.MinioUtil;
import com.jero.modules.laws.common.constant.FieldCommon;
import com.jero.modules.laws.common.constant.ResultCommon;
import com.jero.modules.laws.common.mapper.LawsCommonMapper;
@@ -16,8 +18,10 @@ import com.jero.modules.laws.common.service.ILawsCommonService;
import com.jero.modules.laws.common.vo.ManyStandardSelectionBox;
import com.jero.modules.laws.common.vo.ManyStandardSelectionBoxVO;
import com.jero.modules.laws.standard.entity.LawsNodeRelation;
import com.jero.modules.laws.standard.entity.LawsStandardFile;
import com.jero.modules.laws.standard.service.ILawsNodeRelationService;
import com.jero.modules.laws.standard.service.ILawsReplacedStandardService;
import com.jero.modules.laws.standard.service.ILawsStandardFileService;
import com.jero.modules.laws.standard.service.ILawsUpdateRecordService;
import com.jero.modules.oss.entity.OSSFile;
import com.jero.modules.oss.service.IOSSFileService;
@@ -47,11 +51,15 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @Author: liao
@@ -82,6 +90,8 @@ public class LawsCommonServiceImpl implements ILawsCommonService {
private ILawsNodeRelationService lawsNodeRelationService;
@Autowired
private ILawsReplacedStandardService lawsReplacedStandardService;
@Autowired
private ILawsStandardFileService lawsStandardFileService;
/**
* @Author: liao
@@ -877,17 +887,29 @@ public class LawsCommonServiceImpl implements ILawsCommonService {
public void exportDataWithFile(HttpServletResponse response, Map<String, Object> parameterMap, String sheetName, String fileName) {
try {
// 创建表头
List<LawsTag> headers = this.getExportHeader(parameterMap);
List<LawsTag> headers = this.getExportHeaderWithFile(parameterMap);
// 获取数据
IPage<Map<String, Object>> commonPage = this.getExportData(parameterMap, headers);
List<Map<String, Object>> records = commonPage.getRecords();
// 获取所有标准主键id
// 获取表头中的文件相关类型的对象集合
List<String> standardNos = records.stream().map(r -> r.get("standard_number").toString()).collect(Collectors.toList());
List<LawsTag> fileHeaders = headers.stream().filter(h -> h.getFieldShowType().equals("8")).collect(Collectors.toList());
Map<String, String> fileNameByTypeMap = fileHeaders.stream()
.collect(Collectors.toMap(LawsTag::getDbFieldName, LawsTag::getDbFieldTxt));
// 将文件名设置回数据列表
// 获取所有文件
Map<String, List<LawsStandardFile>> fileMap = lawsStandardFileService.getAllFiles(standardNos);
// 设置文件字段
lawsStandardFileService.setRecordFile(records, standardNos, fileHeaders);
// 创建Excel
ByteArrayOutputStream excelOutputStream = new ByteArrayOutputStream();
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(sheetName);
// Excel填充内容
Row headerRow = sheet.createRow(0);
for (int i = 0; i < headers.size(); i++) {
Cell headerCell = headerRow.createCell(i);
@@ -907,19 +929,117 @@ public class LawsCommonServiceImpl implements ILawsCommonService {
}
}
// 设置响应头和内容类型
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
// 写出到响应流
workbook.write(response.getOutputStream());
// 保存Excel到OutputStream
workbook.write(excelOutputStream);
workbook.close();
// 准备ZIP
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".zip");
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
// 将Excel加入ZIP
ZipEntry excelEntry = new ZipEntry(fileName + ".xlsx");
zipOut.putNextEntry(excelEntry);
byte[] bytes = excelOutputStream.toByteArray();
zipOut.write(bytes, 0, bytes.length);
zipOut.closeEntry();
// 将文件和文件夹加入ZIP
for (Map.Entry<String, List<LawsStandardFile>> entry : fileMap.entrySet()) {
String folderName = entry.getKey();
List<LawsStandardFile> files = entry.getValue();
// 收集所有文件id
List<String> fileIds = files.stream()
.map(LawsStandardFile::getFileId)
.collect(Collectors.toList());
// 找到所有文件记录
Map<String, OSSFile> ossFileMap = ossFileService.listByIds(fileIds)
.stream()
.collect(Collectors.toMap(OSSFile::getId, Function.identity()));
List<String> filePathList = new ArrayList<>();
Map<String, Integer> nameCountMap = new HashMap<>();
for (LawsStandardFile file : files) {
String fileNameByType = fileNameByTypeMap.get(file.getFileType());
String baseFilePath = folderName + "/" + fileNameByType;
String currentFilePath = baseFilePath;
if (filePathList.contains(currentFilePath)) {
int count = nameCountMap.getOrDefault(baseFilePath, 1);
// 更新之前的名字
int index = filePathList.indexOf(currentFilePath);
filePathList.set(index, baseFilePath + count);
// 更新当前名字
count++;
currentFilePath = baseFilePath + count;
nameCountMap.put(baseFilePath, count + 1);
} else if (nameCountMap.containsKey(baseFilePath)) {
int count = nameCountMap.get(baseFilePath);
currentFilePath = baseFilePath + count;
nameCountMap.put(baseFilePath, count + 1);
}
filePathList.add(currentFilePath);
}
Iterator<String> iterator = filePathList.iterator();
for (LawsStandardFile file : files) {
if (iterator.hasNext()) {
String updatedFilePath = iterator.next();
file.setFileName(updatedFilePath);
}
}
for (LawsStandardFile file : files) {
OSSFile ossFile = ossFileMap.get(file.getFileId());
String fileExtension = FileUtil.extName(ossFile.getFileName());
String filePath = file.getFileName() + "." + fileExtension;
ZipEntry fileEntry = new ZipEntry(filePath);
zipOut.putNextEntry(fileEntry);
// 将文件取出存入流中
bytes = getMinioFileContent(ossFile);
zipOut.write(bytes, 0, bytes.length);
zipOut.closeEntry();
}
}
zipOut.close();
} catch (Exception e) {
log.error("导出excel异常", e);
throw new JeroBootException("导出excel异常", e);
log.error("导出zip异常", e);
throw new JeroBootException("导出zip异常", e);
}
}
private byte[] getMinioFileContent(OSSFile file) throws Exception {
String fileUrl = file.getUrl();
String minioUrl = MinioUtil.getMinioUrl();
minioUrl = minioUrl + MinioUtil.getBucketName() + "/";
String url = fileUrl.replace(minioUrl, "");
try (InputStream inputStream = MinioUtil.getMinioFile(MinioUtil.getBucketName(), url);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
) {
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
}
return outputStream.toByteArray();
} catch (Exception e) {
log.error(e.getMessage());
throw e;
}
}
/**
* @Author: liao
@@ -18,10 +18,10 @@ import lombok.experimental.Accessors;
* @TableName laws_standard_file
*/
@Data
@TableName("laws_update_record")
@TableName("laws_standard_file")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="laws_update_record对象", description="更新记录")
@ApiModel(value="laws_standard_file对象", description="标准文件")
public class LawsStandardFile implements Serializable {
/**
* 主键ID
@@ -84,6 +84,20 @@ public class LawsStandardFile implements Serializable {
@ApiModelProperty(value = "所属模块编码")
private String moduleCode;
/**
* 文件名
*/
@TableField(exist = false)
@ApiModelProperty(value = "文件名")
private String fileName;
/**
* 真实存储的文件名
*/
@TableField(exist = false)
@ApiModelProperty(value = "真实存储的文件名")
private String fileDiskName;
@TableField(exist = false)
private static final long serialVersionUID = 1978687668756786786L;
}
@@ -2,6 +2,9 @@ package com.jero.modules.laws.standard.mapper;
import com.jero.modules.laws.standard.entity.LawsStandardFile;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author ThinkBook
@@ -11,6 +14,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface LawsStandardFileMapper extends BaseMapper<LawsStandardFile> {
List<LawsStandardFile> getFilesByStandardNos(@Param("standardNos") List<String> standardNos);
}
@@ -23,4 +23,20 @@
standard_no,file_id,file_type,
module_code
</sql>
<select id="getFilesByStandardNos" resultType="com.jero.modules.laws.standard.entity.LawsStandardFile">
SELECT
sf.id,
sf.standard_no,
o.id AS fileId,
sf.file_type,
sf.module_code,
o.file_name AS fileDiskName
FROM laws_standard_file AS sf
LEFT JOIN oss_file AS O ON sf.file_id = O.id
WHERE sf.standard_no IN
<foreach item="item" index="index" collection="standardNos" open="(" separator="," close=")">
#{item}
</foreach>
</select>
</mapper>
@@ -2,6 +2,10 @@ package com.jero.modules.laws.standard.service;
import com.jero.modules.laws.standard.entity.LawsStandardFile;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jero.modules.tag.entity.LawsTag;
import java.util.List;
import java.util.Map;
/**
* @author ThinkBook
@@ -10,4 +14,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface ILawsStandardFileService extends IService<LawsStandardFile> {
/**
* 根据标准编号集合获取文件列表
* @param standardNos
* @return
*/
Map<String, List<LawsStandardFile>> getAllFiles(List<String> standardNos);
void setRecordFile(List<Map<String, Object>> records, List<String> standardNos, List<LawsTag> fileHeaders);
}
@@ -1,23 +1,89 @@
package com.jero.modules.laws.standard.service.impl;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jero.common.exception.JeroBootException;
import com.jero.common.system.api.ISysBaseAPI;
import com.jero.modules.laws.standard.entity.LawsStandardFile;
import com.jero.modules.laws.standard.service.ILawsStandardFileService;
import com.jero.modules.laws.standard.mapper.LawsStandardFileMapper;
import com.jero.modules.tag.entity.LawsTag;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author ThinkBook
* @description 针对表【laws_standard_file】的数据库操作Service实现
* @createDate 2023-09-20 10:45:16
*/
* @author ThinkBook
* @description 针对表【laws_standard_file】的数据库操作Service实现
* @createDate 2023-09-20 10:45:16
*/
@Service
@Transactional(rollbackFor = JeroBootException.class)
public class LawsStandardFileServiceImpl extends ServiceImpl<LawsStandardFileMapper, LawsStandardFile>
implements ILawsStandardFileService {
implements ILawsStandardFileService {
@Resource
private LawsStandardFileMapper standardFileMapper;
@Override
public Map<String, List<LawsStandardFile>> getAllFiles(List<String> standardNos) {
// 找到所有相关文件
LambdaQueryWrapper<LawsStandardFile> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(LawsStandardFile::getStandardNo, standardNos);
List<LawsStandardFile> list = list(queryWrapper);
// 将List转成Map
return list.stream()
.collect(Collectors.groupingBy(LawsStandardFile::getStandardNo));
}
@Override
public void setRecordFile(List<Map<String, Object>> records, List<String> standardNos, List<LawsTag> fileHeaders) {
// 找到所有相关文件
LambdaQueryWrapper<LawsStandardFile> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(LawsStandardFile::getStandardNo, standardNos);
List<LawsStandardFile> list = standardFileMapper.getFilesByStandardNos(standardNos);
// 按照标准编号和文件类型分组
Map<String, List<LawsStandardFile>> groupMap = list.stream()
.collect(Collectors.groupingBy(
sf -> sf.getStandardNo() + "-" + sf.getFileType() // Key: standardNo-fileType
));
// 遍历每个记录
for (Map<String, Object> record : records) {
String standardNo = (String) record.get("standard_number");
for (LawsTag tag : fileHeaders) {
String fileName = tag.getDbFieldTxt();
String key = standardNo + "-" + tag.getDbFieldName();
List<LawsStandardFile> lawsStandardFiles = groupMap.get(key);
if (lawsStandardFiles == null) {
continue;
}
StringBuilder allFileName = new StringBuilder();
// 遍历找到的结果
if (lawsStandardFiles.size() == 1) {
String fileExtension = "." + FileUtil.extName(lawsStandardFiles.get(0).getFileDiskName());
allFileName = new StringBuilder(standardNo + "/" + fileName + fileExtension);
} else {
for (int i = 1; i <= lawsStandardFiles.size(); i++) {
String fileExtension = "." + FileUtil.extName(lawsStandardFiles.get(0).getFileDiskName());
allFileName.append(standardNo).append("/").append(fileName).append(i).append(fileExtension).append(",");
}
// 去除最后一个,
allFileName = new StringBuilder(allFileName.substring(0, allFileName.length() - 1));
}
// 最终设置
record.put(tag.getDbFieldName(), allFileName.toString());
}
}
}
}