From d448628f550fd3cf87d660d5cc417fe28918fa6f Mon Sep 17 00:00:00 2001 From: lenovo Date: Thu, 17 Nov 2022 17:41:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 + .../com/gmh/config/LocalFileAutoConfig.java | 81 ++++++ .../com/gmh/controller/ExcelController.java | 264 ++++++++++++------ src/main/java/com/gmh/dao/GmhFileLogDao.java | 9 + src/main/java/com/gmh/entity/BaseEntity.java | 1 + src/main/java/com/gmh/entity/ExcelInfo.java | 38 +++ src/main/java/com/gmh/entity/GmhFileLog.java | 49 ++++ .../properties/FileServerProperties.java | 28 ++ .../entity/properties/LocalProperties.java | 18 ++ .../gmh/entity/properties/OssProperties.java | 26 ++ .../entity/query/ExecuteTemplateQuery.java | 24 ++ .../java/com/gmh/service/FileService.java | 3 + .../com/gmh/service/GmhFileLogService.java | 10 + .../com/gmh/service/impl/FileServiceImpl.java | 73 +++++ .../service/impl/GmhFileLogServiceImpl.java | 27 ++ src/main/java/com/gmh/utils/POIExcelUtil.java | 134 +++++++-- .../{CommonUtils.java => StringUtils.java} | 4 +- .../java/com/gmh/utils/ThrowableUtil.java | 23 ++ src/main/resources/application.properties | 10 + 19 files changed, 711 insertions(+), 117 deletions(-) create mode 100644 src/main/java/com/gmh/config/LocalFileAutoConfig.java create mode 100644 src/main/java/com/gmh/dao/GmhFileLogDao.java create mode 100644 src/main/java/com/gmh/entity/ExcelInfo.java create mode 100644 src/main/java/com/gmh/entity/GmhFileLog.java create mode 100644 src/main/java/com/gmh/entity/properties/FileServerProperties.java create mode 100644 src/main/java/com/gmh/entity/properties/LocalProperties.java create mode 100644 src/main/java/com/gmh/entity/properties/OssProperties.java create mode 100644 src/main/java/com/gmh/entity/query/ExecuteTemplateQuery.java create mode 100644 src/main/java/com/gmh/service/GmhFileLogService.java create mode 100644 src/main/java/com/gmh/service/impl/FileServiceImpl.java create mode 100644 src/main/java/com/gmh/service/impl/GmhFileLogServiceImpl.java rename src/main/java/com/gmh/utils/{CommonUtils.java => StringUtils.java} (79%) create mode 100644 src/main/java/com/gmh/utils/ThrowableUtil.java diff --git a/pom.xml b/pom.xml index 5cf0e96..33f8dec 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,12 @@ 6.0.1.Final + + commons-fileupload + commons-fileupload + 1.4 + + diff --git a/src/main/java/com/gmh/config/LocalFileAutoConfig.java b/src/main/java/com/gmh/config/LocalFileAutoConfig.java new file mode 100644 index 0000000..9a2a634 --- /dev/null +++ b/src/main/java/com/gmh/config/LocalFileAutoConfig.java @@ -0,0 +1,81 @@ +package com.gmh.config; + +import com.gmh.entity.FileEntity; +import com.gmh.entity.properties.FileServerProperties; +import com.gmh.service.impl.FileServiceImpl; +import com.gmh.utils.ThrowableUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Service; +import org.springframework.util.ResourceUtils; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +@Configuration +@ConditionalOnProperty(name = "data.file-server.type", havingValue = "local") +public class LocalFileAutoConfig { + + private final Logger logger = LoggerFactory.getLogger(LocalFileAutoConfig.class); + + @Autowired + private FileServerProperties fileProperties; + + @Bean + public WebMvcConfigurer webMvcConfigurerAdapter() { + return new WebMvcConfigurer() { + /** + * 外部文件访问 + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler(fileProperties.getLocal().getPrefix() + "/**") + .addResourceLocations(ResourceUtils.FILE_URL_PREFIX + fileProperties.getLocal().getPath() + File.separator); + } + }; + } + + @Service + public class LocalFileServiceImpl extends FileServiceImpl { + + @Override + protected String fileType() { + return fileProperties.getType(); + } + + @Override + protected void uploadFile(MultipartFile file, FileEntity fileEntity) { + String localPath = fileProperties.getLocal().getPath(); + File parentFile = new File(localPath); + if (!parentFile.exists()) { + if (!parentFile.mkdirs()) { + throw new RuntimeException("创建保存路径失败"); + } + } + fileEntity.setFilePath(localPath + File.separator + fileEntity.getFileName()); + File dest = new File(localPath + File.separator + fileEntity.getFileName()); + try { + file.transferTo(dest); + } catch (IOException e) { + logger.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e)); + } + } + + @Override + protected void deleteFile(FileEntity fileEntity) { + File file = new File(fileEntity.getFilePath()); + if (file.exists()) { + file.delete(); + } + } + + } +} diff --git a/src/main/java/com/gmh/controller/ExcelController.java b/src/main/java/com/gmh/controller/ExcelController.java index 1817054..1fa8ca2 100644 --- a/src/main/java/com/gmh/controller/ExcelController.java +++ b/src/main/java/com/gmh/controller/ExcelController.java @@ -1,31 +1,37 @@ package com.gmh.controller; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.gmh.entity.GmhUser; -import com.gmh.entity.R; -import com.gmh.entity.RowCellNum; -import com.gmh.entity.SysBaijiaxing; +import com.gmh.entity.*; +import com.gmh.entity.properties.FileServerProperties; +import com.gmh.entity.query.ExecuteTemplateQuery; import com.gmh.entity.vo.ReadNameVo; +import com.gmh.service.GmhFileLogService; +import com.gmh.service.FileService; import com.gmh.service.SysBaijiaxingService; -import com.gmh.utils.CommonUtils; +import com.gmh.utils.StringUtils; import com.gmh.utils.POIExcelUtil; -import com.gmh.utils.RedisUtils; -import com.gmh.utils.RedisUtilsDefault; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.apache.commons.fileupload.disk.DiskFileItem; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.io.IOUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellReference; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.servlet.http.HttpServletResponse; -import javax.validation.constraints.Pattern; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -36,11 +42,19 @@ import java.util.stream.Collectors; @RequestMapping("/excel") public class ExcelController { - private Integer templateSheetNum = null; + @Autowired + private FileService fileService; + + @Autowired + private GmhFileLogService gmhFileLogService; + + @Autowired + private FileServerProperties fileProperties; - private Workbook templateWorkbook = null; + @Autowired + private SysBaijiaxingService baijiaxingService; - private List readNameVoList = null; + private final ExcelInfo excelInfo = new ExcelInfo(); private static final String KEY_XINGMING = "姓名"; @@ -52,57 +66,68 @@ public class ExcelController { return R.ok("ok"); } - @RequestMapping("/readData") - public R readSourceData(MultipartFile file) throws IOException { + @RequestMapping("/dataSourceImport") + public R dataSourceImport(MultipartFile file, String dataSourceImportModel) throws IOException { + DataSourceImportModel importModel = DataSourceImportModel.findEnum(dataSourceImportModel); Workbook workbook = POIExcelUtil.readExcelFromInputStream(file.getInputStream(), file.getOriginalFilename()); - readNameVoList = new ArrayList<>(); - for (int i = 0; i < workbook.getNumberOfSheets(); i++) { - ReadNameVo readNameVo = new ReadNameVo(); - Sheet sheet = workbook.getSheetAt(i); - List> excelMaps = POIExcelUtil.toListMap(sheet); - if (excelMaps.isEmpty()) { - continue; - } - Map firstElement = excelMaps.get(0); - String xmKey = KEY_XINGMING; - for (String key : firstElement.keySet()) { - if (KEY_XINGMING.equals(firstElement.get(key))) { - xmKey = key; + FileEntity fileEntity = fileService.uploadFile(file); + gmhFileLogService.recordLog(fileEntity, GmhFileLog.OperateType.D_S_IMP); + if (DataSourceImportModel.AUTO_NAME.equals(importModel)) { + List readNameVoList = new ArrayList<>(); + for (int i = 0; i < workbook.getNumberOfSheets(); i++) { + ReadNameVo readNameVo = new ReadNameVo(); + Sheet sheet = workbook.getSheetAt(i); + List> excelMaps = POIExcelUtil.toListMap(sheet); + if (excelMaps.isEmpty()) { + continue; } - } - if (firstElement.containsKey(xmKey)) { - if (!KEY_XINGMING.equals(xmKey)) { - excelMaps.remove(firstElement); + Map firstElement = excelMaps.get(0); + String xmKey = KEY_XINGMING; + for (String key : firstElement.keySet()) { + if (KEY_XINGMING.equals(firstElement.get(key))) { + xmKey = key; + } } - readNameVo = getReadNameDataForNameKey(excelMaps, xmKey); - } else { - Map map = new HashMap<>(); - for (Map excelMap : excelMaps) { - for (String key : excelMap.keySet()) { - String value = excelMap.get(key); - if (baijiaxingService.likeChineseName(value)) { - Integer count = map.getOrDefault(key, 0); - map.put(key, ++count); + if (firstElement.containsKey(xmKey)) { + if (!KEY_XINGMING.equals(xmKey)) { + excelMaps.remove(firstElement); + } + readNameVo = getReadNameDataForNameKey(excelMaps, xmKey); + } else { + Map map = new HashMap<>(); + for (Map excelMap : excelMaps) { + for (String key : excelMap.keySet()) { + String value = excelMap.get(key); + if (baijiaxingService.likeChineseName(value)) { + Integer count = map.getOrDefault(key, 0); + map.put(key, ++count); + } } } - } - List> list = new ArrayList<>(map.entrySet()); + List> list = new ArrayList<>(map.entrySet()); // list.sort(Comparator.comparingInt(Map.Entry::getValue)); //升序 - list.sort((o1, o2) -> (o2.getValue() - o1.getValue())); - String key = list.get(0).getKey(); - readNameVo = getReadNameDataForNameKey(excelMaps, key); + list.sort((o1, o2) -> (o2.getValue() - o1.getValue())); + String key = list.get(0).getKey(); + readNameVo = getReadNameDataForNameKey(excelMaps, key); + } + readNameVo.setSheetName(sheet.getSheetName()); + readNameVoList.add(readNameVo); } - readNameVo.setSheetName(sheet.getSheetName()); - readNameVoList.add(readNameVo); + excelInfo.setReadNameVoList(readNameVoList); + return R.ok().setData(readNameVoList); } - return R.ok().setData(readNameVoList); + return R.error(); + } public ReadNameVo getReadNameDataForNameKey(List> excelMaps, final String key) { ReadNameVo readNameVo = new ReadNameVo(); // 去重前 - List oldNameList = excelMaps.stream().map(map -> new GmhUser(map.get(key))).collect(Collectors.toList()); + List oldNameList = excelMaps.stream() + .map(map -> new GmhUser(map.get(key))) + .filter(item -> StringUtils.isNotBlank(item.getName())) + .collect(Collectors.toList()); // 去重后 LinkedHashSet newNameList = new LinkedHashSet<>(oldNameList); readNameVo.setNameList(newNameList); @@ -118,24 +143,34 @@ public class ExcelController { return readNameVo; } + /** + * 模板导入 + * @param file excel文件 + * @param templateSheetNum 模板所在Sheet页 + * @return + * @throws IOException + */ @RequestMapping("/template") public R templateUpload(MultipartFile file, String templateSheetNum) throws IOException { Workbook workbook = POIExcelUtil.readExcelFromInputStream(file.getInputStream(), file.getOriginalFilename()); - this.templateSheetNum = Integer.parseInt(templateSheetNum) - 1; - Sheet sheet = workbook.getSheetAt(this.templateSheetNum); + FileEntity fileEntity = fileService.uploadFile(file); + gmhFileLogService.recordLog(fileEntity, GmhFileLog.OperateType.TEMPL_IMP); + excelInfo.setTemplateOriginalFilename(file.getOriginalFilename()); + excelInfo.setTemplateSheetNum(Integer.parseInt(templateSheetNum) - 1); + Sheet sheet = workbook.getSheetAt(excelInfo.getTemplateSheetNum()); if (sheet == null) { throw new RuntimeException("sheet页不存在"); } - this.templateWorkbook = workbook; + excelInfo.setTemplateWorkbook(workbook); return R.ok(); } @RequestMapping("/cellNumSearch") public R analysisCell(@Validated RowCellNum rowCellNum) { - if (this.templateWorkbook == null) { + if (excelInfo.getTemplateWorkbook() == null) { return R.error("模板文件出问题了,请重新上传"); } - Sheet sheet = this.templateWorkbook.getSheetAt(this.templateSheetNum); + Sheet sheet = excelInfo.getTemplateWorkbook().getSheetAt(excelInfo.getTemplateSheetNum()); rowCellNum = POIExcelUtil.analysisCellRowNum(rowCellNum); Row row = sheet.getRow(rowCellNum.getRowNum()); if (row == null) { @@ -152,15 +187,17 @@ public class ExcelController { return R.ok().setData(stringCellVal); } - @RequestMapping("/executeTemplate") - public void executeTemplate(String newCellData, String cellRowStr, HttpServletResponse response) throws IOException { + + @PostMapping("/executeTemplate") + public R executeTemplate(@RequestBody ExecuteTemplateQuery executeTemplateQuery) throws IOException { + String newCellData = executeTemplateQuery.getNewCellData(); String expr = newCellData.substring(newCellData.indexOf("@{"), newCellData.indexOf("}") + 1); String exprVal = newCellData.substring(newCellData.indexOf("@{") + 2, newCellData.indexOf("}")); String[] exprArr = exprVal.split("\\."); String sheetName = exprArr[0]; String field = exprArr[1]; - Optional first = readNameVoList + Optional first = excelInfo.getReadNameVoList() .stream() .filter(item -> item.getSheetName().equalsIgnoreCase(sheetName)) .findFirst(); @@ -168,45 +205,77 @@ public class ExcelController { throw new RuntimeException("未找到sheet页,可能是表达式错误"); } ReadNameVo readNameVo = first.get(); - POIExcelUtil.removeModelSheet(this.templateWorkbook, this.templateSheetNum); - POIExcelUtil.batchCloneSheet(this.templateWorkbook, this.templateSheetNum, readNameVo.getNameList().size()); + POIExcelUtil.removeModelSheet(excelInfo.getTemplateWorkbook(), excelInfo.getTemplateSheetNum()); + POIExcelUtil.batchCloneSheet(excelInfo.getTemplateWorkbook(), excelInfo.getTemplateSheetNum(), readNameVo.getNameList().size()); ArrayList gmhUsers = new ArrayList<>(readNameVo.getNameList()); - RowCellNum rowCellNum = POIExcelUtil.analysisCellRowNum(cellRowStr); - for (int i = 0; i < this.templateWorkbook.getNumberOfSheets(); i++) { - Sheet sheet = templateWorkbook.getSheetAt(i); + RowCellNum rowCellNum = POIExcelUtil.analysisCellRowNum(executeTemplateQuery.getCellRowStr()); + for (int i = 0; i < excelInfo.getTemplateWorkbook().getNumberOfSheets(); i++) { + Sheet sheet = excelInfo.getTemplateWorkbook().getSheetAt(i); if (sheet == null) { continue; } Row row = sheet.getRow(rowCellNum.getRowNum()); Cell cell = row.getCell(rowCellNum.getCellNum()); - cell.setCellValue(newCellData.replace(expr, CommonUtils.nameFormat(gmhUsers.get(i).getName()))); + cell.setCellValue(newCellData.replace(expr, StringUtils.nameFormat(gmhUsers.get(i).getName()))); } - // TODO 文件保存到本地,文件信息入库 + String localPath = fileProperties.getLocal().getPath(); + File parentFile = new File(localPath); + if (!parentFile.exists()) { + if (!parentFile.mkdirs()) { + throw new RuntimeException("创建保存路径失败"); + } + } + FileEntity fileEntity = new FileEntity(); + String extName = FileUtil.extName(excelInfo.getTemplateOriginalFilename()); + String originalFilename; + if (StringUtils.isBlank(executeTemplateQuery.getResultExcelName())) { + originalFilename = excelInfo.getTemplateOriginalFilename(); + } else { + originalFilename = executeTemplateQuery.getResultExcelName() + "." + extName; + } + fileEntity.setContentType(MediaType.ALL_VALUE) + .setOriginalFilename(originalFilename) + .setFileSize(2222L); + fileEntity.setFileType(fileProperties.getType()); + String nowDate = DateUtil.format(new Date(), "yyyyMMddHHmmss"); + fileEntity.setFileName(nowDate + "." + extName); + File dest = new File(localPath + File.separator + fileEntity.getFileName()); + fileEntity.setFilePath(localPath + File.separator + fileEntity.getFileName()); + FileOutputStream fout = null; + try { + fout = new FileOutputStream(dest); + excelInfo.getTemplateWorkbook().write(fout); + fileService.save(fileEntity); + gmhFileLogService.recordLog(fileEntity, GmhFileLog.OperateType.TEMPL_EXP); + } finally { + assert fout != null; + fout.close(); +// excelInfo.getTemplateWorkbook().close(); + } + return R.ok(); - // 输出Excel文件 - OutputStream output = response.getOutputStream(); - response.reset(); - // 设置文件头 - response.setHeader("Content-Disposition", - "attchement;filename=" + new String((sheetName + ".xls").getBytes("gb2312"), "ISO8859-1")); - response.setContentType("application/msexcel"); - this.templateWorkbook.write(output); - this.templateWorkbook.close(); + // 输出Excel文件 下载出去 +// OutputStream output = response.getOutputStream(); +// response.reset(); +// // 设置文件头 +// response.setHeader("Content-Disposition", +// "attchement;filename=" + new String((sheetName + ".xls").getBytes("gb2312"), "ISO8859-1")); +// response.setContentType("application/msexcel"); +// excelInfo.getTemplateWorkbook().write(fout); +// excelInfo.getTemplateWorkbook().close(); -// try { -// FileOutputStream out = new FileOutputStream("C:\\Users\\admin\\Desktop\\tempfile\\output\\out的222.xls"); -// out.flush(); -// templateWorkbook.write(out); -// out.close(); -// System.out.println("文件输出完成"); -// } catch (IOException e) { -// e.printStackTrace(); -// } } - @Autowired - private SysBaijiaxingService baijiaxingService; + @GetMapping("/gotoDownload") + public R gotoDownload() { + try { + excelInfo.getTemplateWorkbook().close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return R.ok(); + } private boolean isChinaName(String val) { QueryWrapper queryWrapper = new QueryWrapper<>(); @@ -270,4 +339,27 @@ public class ExcelController { // return R.ok().setData(readNameList); } + /** + * 数据源导入模式枚举 + */ + @Getter + @AllArgsConstructor + public enum DataSourceImportModel { + + AUTO_NAME("0", "自动识别姓名"), + ALL("1", "全部导入"); + + private final String value; + private final String remark; + + public static DataSourceImportModel findEnum(String value) { + for (DataSourceImportModel item : values()) { + if (value.equals(item.getValue())) { + return item; + } + } + throw new RuntimeException("没有找到对应的枚举"); + } + } + } diff --git a/src/main/java/com/gmh/dao/GmhFileLogDao.java b/src/main/java/com/gmh/dao/GmhFileLogDao.java new file mode 100644 index 0000000..7d78ac4 --- /dev/null +++ b/src/main/java/com/gmh/dao/GmhFileLogDao.java @@ -0,0 +1,9 @@ +package com.gmh.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gmh.entity.GmhFileLog; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface GmhFileLogDao extends BaseMapper { +} diff --git a/src/main/java/com/gmh/entity/BaseEntity.java b/src/main/java/com/gmh/entity/BaseEntity.java index 9f785ee..3385699 100644 --- a/src/main/java/com/gmh/entity/BaseEntity.java +++ b/src/main/java/com/gmh/entity/BaseEntity.java @@ -3,6 +3,7 @@ package com.gmh.entity; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; +import lombok.experimental.Accessors; import java.io.Serializable; import java.time.LocalDateTime; diff --git a/src/main/java/com/gmh/entity/ExcelInfo.java b/src/main/java/com/gmh/entity/ExcelInfo.java new file mode 100644 index 0000000..3d83833 --- /dev/null +++ b/src/main/java/com/gmh/entity/ExcelInfo.java @@ -0,0 +1,38 @@ +package com.gmh.entity; + +import com.gmh.entity.vo.ReadNameVo; +import lombok.Getter; +import lombok.Setter; +import org.apache.poi.ss.usermodel.Workbook; + +import java.util.List; + +@Getter +@Setter +public class ExcelInfo { + + /** + * 模板所在Sheet页索引 + */ + private Integer templateSheetNum; + + /** + * 模板workbook对象 + */ + private Workbook templateWorkbook; + + /** + * 源数据 + */ + private List readNameVoList; + + /** + * 模板原始文件名 + */ + private String templateOriginalFilename; + + /** + * 文件大小 + */ + private Long size; +} diff --git a/src/main/java/com/gmh/entity/GmhFileLog.java b/src/main/java/com/gmh/entity/GmhFileLog.java new file mode 100644 index 0000000..68b540d --- /dev/null +++ b/src/main/java/com/gmh/entity/GmhFileLog.java @@ -0,0 +1,49 @@ +package com.gmh.entity; + +import com.gmh.controller.ExcelController; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + * 文件日志 + */ +@Getter +@Setter +@Accessors(chain = true) +public class GmhFileLog extends BaseEntity{ + + /** + * 文件id + */ + private String fileId; + /** + * 操作类型 + */ + private String operateType; + + /** + * 文件操作类型 + */ + @Getter + @AllArgsConstructor + public enum OperateType { + + D_S_IMP("0", "数据源导入"), + TEMPL_IMP("1", "模板导入"), + TEMPL_EXP("2", "模板导出"); + + private final String value; + private final String remark; + + public static GmhFileLog.OperateType findEnum(String value) { + for (GmhFileLog.OperateType item : values()) { + if (value.equals(item.getValue())) { + return item; + } + } + throw new RuntimeException("没有找到对应的枚举"); + } + } +} diff --git a/src/main/java/com/gmh/entity/properties/FileServerProperties.java b/src/main/java/com/gmh/entity/properties/FileServerProperties.java new file mode 100644 index 0000000..3902447 --- /dev/null +++ b/src/main/java/com/gmh/entity/properties/FileServerProperties.java @@ -0,0 +1,28 @@ +package com.gmh.entity.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "data.file-server") +public class FileServerProperties { + /** + * 为以下4个值,指定不同的自动化配置 + * qiniu:七牛云oss + * aliyun:阿里云oss + * local:本地盘符部署 + */ + private String type; + + /** + * oss配置 + */ + OssProperties oss = new OssProperties(); + + /** + * local配置 + */ + LocalProperties local = new LocalProperties(); +} diff --git a/src/main/java/com/gmh/entity/properties/LocalProperties.java b/src/main/java/com/gmh/entity/properties/LocalProperties.java new file mode 100644 index 0000000..466af77 --- /dev/null +++ b/src/main/java/com/gmh/entity/properties/LocalProperties.java @@ -0,0 +1,18 @@ +package com.gmh.entity.properties; + +import lombok.Data; + +/** + * 本地文件上传配置 + */ +@Data +public class LocalProperties { + /** + * 上传文件存储在本地的根路径 + */ + private String path; + /** + * url访问前缀 + */ + private String prefix; +} diff --git a/src/main/java/com/gmh/entity/properties/OssProperties.java b/src/main/java/com/gmh/entity/properties/OssProperties.java new file mode 100644 index 0000000..8252e6b --- /dev/null +++ b/src/main/java/com/gmh/entity/properties/OssProperties.java @@ -0,0 +1,26 @@ +package com.gmh.entity.properties; + +import lombok.Data; + +/** + * 阿里云OSS配置 + */ +@Data +public class OssProperties { + /** + * 密钥key + */ + private String accessKey; + /** + * 密钥密码 + */ + private String accessKeySecret; + /** + * 存储空间名称 + */ + private String bucketName; + /** + * 对象存储绑定的访问主机域名 + */ + private String domainName; +} diff --git a/src/main/java/com/gmh/entity/query/ExecuteTemplateQuery.java b/src/main/java/com/gmh/entity/query/ExecuteTemplateQuery.java new file mode 100644 index 0000000..0eb216d --- /dev/null +++ b/src/main/java/com/gmh/entity/query/ExecuteTemplateQuery.java @@ -0,0 +1,24 @@ +package com.gmh.entity.query; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ExecuteTemplateQuery { + + /** + * 替换的新内容 + */ + private String newCellData; + + /** + * 单元格逻辑位置 + */ + private String cellRowStr; + + /** + * 生成Excel的名字 + */ + private String resultExcelName; +} diff --git a/src/main/java/com/gmh/service/FileService.java b/src/main/java/com/gmh/service/FileService.java index 7b1066d..d8ade42 100644 --- a/src/main/java/com/gmh/service/FileService.java +++ b/src/main/java/com/gmh/service/FileService.java @@ -1,9 +1,12 @@ package com.gmh.service; + import com.baomidou.mybatisplus.extension.service.IService; import com.gmh.entity.FileEntity; import org.springframework.web.multipart.MultipartFile; +import java.io.OutputStream; + public interface FileService extends IService { FileEntity uploadFile(MultipartFile file); diff --git a/src/main/java/com/gmh/service/GmhFileLogService.java b/src/main/java/com/gmh/service/GmhFileLogService.java new file mode 100644 index 0000000..ba9bc70 --- /dev/null +++ b/src/main/java/com/gmh/service/GmhFileLogService.java @@ -0,0 +1,10 @@ +package com.gmh.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gmh.entity.GmhFileLog; +import com.gmh.entity.FileEntity; + +public interface GmhFileLogService extends IService { + + void recordLog(FileEntity fileEntity, GmhFileLog.OperateType operateType); +} diff --git a/src/main/java/com/gmh/service/impl/FileServiceImpl.java b/src/main/java/com/gmh/service/impl/FileServiceImpl.java new file mode 100644 index 0000000..1439105 --- /dev/null +++ b/src/main/java/com/gmh/service/impl/FileServiceImpl.java @@ -0,0 +1,73 @@ +package com.gmh.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gmh.dao.FileDao; +import com.gmh.entity.FileEntity; +import com.gmh.service.FileService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Date; + +@Service +@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) +public abstract class FileServiceImpl extends ServiceImpl implements FileService { + + @Autowired + private FileDao fileDao; + + @Override + public FileEntity uploadFile(MultipartFile file) { + FileEntity fileEntity = new FileEntity(); + fileEntity.setContentType(file.getContentType()) + .setOriginalFilename(file.getOriginalFilename()) + .setFileSize(file.getSize()); + String nowDate = DateUtil.format(new Date(), "yyyyMMddHHmmss"); + String extName = FileUtil.extName(fileEntity.getOriginalFilename()); + String fileName = nowDate + "." + extName; + fileEntity.setFileName(fileName); + uploadFile(file, fileEntity); + // 设置文件来源 + fileEntity.setFileType(fileType()); + // 将文件信息保存到数据库 + fileDao.insert(fileEntity); + return fileEntity; + } + + @Override + public void deleteFileById(String id) { + FileEntity fileEntity = fileDao.selectById(id); + if (fileEntity != null) { + fileDao.deleteById(fileEntity.getId()); + deleteFile(fileEntity); + } + } + + /** + * 文件来源 + * + * @return + */ + protected abstract String fileType(); + + /** + * 上传文件 + * + * @param file + * @param fileEntity + */ + protected abstract void uploadFile(MultipartFile file, FileEntity fileEntity); + + /** + * 删除文件资源 + * + * @param fileEntity + * @return + */ + protected abstract void deleteFile(FileEntity fileEntity); +} \ No newline at end of file diff --git a/src/main/java/com/gmh/service/impl/GmhFileLogServiceImpl.java b/src/main/java/com/gmh/service/impl/GmhFileLogServiceImpl.java new file mode 100644 index 0000000..1160295 --- /dev/null +++ b/src/main/java/com/gmh/service/impl/GmhFileLogServiceImpl.java @@ -0,0 +1,27 @@ +package com.gmh.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gmh.dao.GmhFileLogDao; +import com.gmh.entity.GmhFileLog; +import com.gmh.entity.FileEntity; +import com.gmh.service.GmhFileLogService; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +@Service +public class GmhFileLogServiceImpl extends ServiceImpl implements GmhFileLogService { + + @Override + public void recordLog(FileEntity fileEntity, GmhFileLog.OperateType operateType) { + GmhFileLog gmhFileLog = new GmhFileLog(); + gmhFileLog.setStatus("0"); + gmhFileLog.setFileId(fileEntity.getId()); + gmhFileLog.setCreateTime(LocalDateTime.now()); + gmhFileLog.setCreateBy("gmh"); + gmhFileLog.setUpdateTime(LocalDateTime.now()); + gmhFileLog.setUpdateBy("gmh"); + gmhFileLog.setOperateType(operateType.getValue()); + save(gmhFileLog); + } +} diff --git a/src/main/java/com/gmh/utils/POIExcelUtil.java b/src/main/java/com/gmh/utils/POIExcelUtil.java index c175a67..0353ca5 100644 --- a/src/main/java/com/gmh/utils/POIExcelUtil.java +++ b/src/main/java/com/gmh/utils/POIExcelUtil.java @@ -1,23 +1,28 @@ package com.gmh.utils; +import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.ExcelFileUtil; import com.gmh.entity.RowCellNum; -import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * POI Excel工具类 - * created on 2020/5/28 10:08 * - * @author puhaiyang + * @author Chenda */ public class POIExcelUtil { @@ -34,48 +39,83 @@ public class POIExcelUtil { } } - public static Workbook cloneSheet(Workbook workbook, String srcSheetName, String destSheetName) { + /** + * 克隆一个Sheet + * + * @param workbook workbook + * @param srcSheetName 原始sheet页名字 + * @param newSheetName 新sheet页名字 + */ + public static void cloneSheet(Workbook workbook, String srcSheetName, String newSheetName) { int index = workbook.getSheetIndex(srcSheetName); - return cloneSheet(workbook, index, destSheetName); + cloneSheet(workbook, index, newSheetName); } - public static Workbook cloneSheet(Workbook workbook, Integer index, String destSheetName) { + /** + * 克隆一个Sheet + * + * @param workbook workbook + * @param index 原始sheet页索引 + * @param newSheetName 新sheet页名字 + */ + public static void cloneSheet(Workbook workbook, Integer index, String newSheetName) { //克隆一个新的sheet Sheet newSheet = workbook.cloneSheet(index); int sheetIndex = workbook.getSheetIndex(newSheet); - workbook.setSheetName(sheetIndex, destSheetName); - return workbook; + workbook.setSheetName(sheetIndex, newSheetName); } - public static Workbook cloneSheet(File excelFile, Integer index, String destSheetName) throws IOException { + /** + * 克隆一个Sheet + * + * @param excelFile excel文件 + * @param index 原始sheet页索引 + * @param newSheetName 新sheet页名字 + * @throws IOException exception + */ + public static void cloneSheet(File excelFile, Integer index, String newSheetName) throws IOException { Workbook workbook = readExcelFromFile(excelFile); - return cloneSheet(workbook, index, destSheetName); + cloneSheet(workbook, index, newSheetName); } /** * 复制多个sheet + * 复制出来的新sheet会按照自然排序数字进行命名,如:1 2 3 4 ... * * @param workbook workbook * @param index 起始sheet - * @param total 复制多个sheet + * @param total 想要复制多少(复制后会删除原始sheet,此参数只需指定总数即可) */ - public static Workbook batchCloneSheet(Workbook workbook, Integer index, Integer total) throws IOException { + public static Workbook batchCloneSheet(Workbook workbook, Integer index, Integer total) { + // 将原始sheet重新命名,防止复制出来的新sheet与它重名 + workbook.setSheetName(index, RandomUtil.randomString(5)); for (int i = 0; i < total; i++) { - //克隆一个新的sheet - Sheet newSheet = workbook.cloneSheet(index); - int sheetIndex = workbook.getSheetIndex(newSheet); - workbook.setSheetName(sheetIndex, String.valueOf(i + 1)); + cloneSheet(workbook, index, String.valueOf(i + 1)); } workbook.removeSheetAt(index); return workbook; } + /** + * 复制多个sheet + * 复制出来的新sheet会按照自然排序数字进行命名,如:1 2 3 4 ... + * + * @param excelFile excel文件 + * @param index 起始sheet + * @param total 想要复制多少(复制后会删除原始sheet,此参数只需指定总数即可) + */ public static Workbook batchCloneSheet(File excelFile, Integer index, Integer total) throws IOException { Workbook workbook = readExcelFromFile(excelFile); return batchCloneSheet(workbook, index, total); } - //读取excel + /** + * 从文件中读取excel + * + * @param file excel文件 + * @return Workbook + * @throws IOException exception + */ public static Workbook readExcelFromFile(File file) throws IOException { if (file == null) { throw new RuntimeException("文件为空"); @@ -83,10 +123,26 @@ public class POIExcelUtil { return readExcelFromInputStream(Files.newInputStream(file.toPath()), file.getName()); } + /** + * 从流中读取excel + * + * @param inputStream inputStream + * @return Workbook + * @throws IOException exception + */ + @Deprecated public static Workbook readExcelFromInputStream(InputStream inputStream) throws IOException { return readExcelFromInputStream(inputStream, null); } + /** + * 从流中读取excel + * + * @param inputStream inputStream + * @param fileName 文件名 + * @return Workbook + * @throws IOException exception + */ public static Workbook readExcelFromInputStream(InputStream inputStream, String fileName) throws IOException { if (StrUtil.isNotBlank(fileName)) { String[] split = fileName.split("\\."); @@ -111,10 +167,26 @@ public class POIExcelUtil { } } + /** + * 从excel单元格中获取字符串类型的值,会排除字符串中的所有空格 + * 例: + * - "张 叁" -> "张叁" + * - "麻花 " -> "麻花" + * - " 瑶 海 " -> "瑶海" + * + * @param cell cell + * @return cellValue + */ public static String getStringCellValExcludeBlank(Cell cell) { return getStringCellVal(cell).replaceAll("\\s*", ""); } + /** + * 从excel单元格中获取字符串类型的值 + * + * @param cell cell + * @return cellValue + */ public static String getStringCellVal(Cell cell) { DataFormatter dataFormatter = new DataFormatter(); return dataFormatter.formatCellValue(cell); @@ -123,9 +195,9 @@ public class POIExcelUtil { /** * Excel 转换为List>对象 * - * @param workbook workbook - * @param sheetIndex 当前sheet页索引 - * @return List> + * @param workbook workbook + * @param sheetIndex 当前sheet页索引 + * @return List> */ public static List> toListMap(Workbook workbook, int sheetIndex) { return toListMap(workbook, sheetIndex, -1); @@ -137,17 +209,17 @@ public class POIExcelUtil { * @param workbook workbook * @param sheetIndex 当前sheet页索引 * @param titleRowNum 标题行索引,索引值<0则代表没有标题行 - * @return List> + * @return List> */ public static List> toListMap(Workbook workbook, int sheetIndex, int titleRowNum) { return toListMap(workbook.getSheetAt(sheetIndex), titleRowNum); } /** - * Excel 转换为List>对象 + * Excel 转换为List>对象,没有title行的 * - * @param sheet workbook - * @return List> + * @param sheet workbook + * @return List> */ public static List> toListMap(Sheet sheet) { return toListMap(sheet, -1); @@ -156,9 +228,9 @@ public class POIExcelUtil { /** * Excel 转换为List>对象 * - * @param sheet 当前sheet页对象 + * @param sheet 当前sheet页对象 * @param titleRowNum 标题行索引,索引值<0则代表没有标题行 - * @return List> + * @return List> */ public static List> toListMap(Sheet sheet, int titleRowNum) { List> list = new ArrayList<>(); @@ -215,7 +287,7 @@ public class POIExcelUtil { */ public static void removeModelSheet(Workbook wb, Sheet noDelSheet) { int sheetIndex = wb.getSheetIndex(noDelSheet); - removeModelSheet(wb,sheetIndex); + removeModelSheet(wb, sheetIndex); } /** @@ -223,7 +295,7 @@ public class POIExcelUtil { */ public static void removeModelSheet(Workbook wb, String name) { int sheetIndex = wb.getSheetIndex(wb.getSheet(name)); - removeModelSheet(wb,sheetIndex); + removeModelSheet(wb, sheetIndex); } /** @@ -242,6 +314,7 @@ public class POIExcelUtil { /** * 将单元格逻辑坐标转换为物理坐标 + * * @param cellRowStr 字符串形式的单元格坐标 如:A3 * @return */ @@ -251,6 +324,7 @@ public class POIExcelUtil { /** * 将单元格逻辑坐标转换为物理坐标 + * * @param rowCellNum * @return */ diff --git a/src/main/java/com/gmh/utils/CommonUtils.java b/src/main/java/com/gmh/utils/StringUtils.java similarity index 79% rename from src/main/java/com/gmh/utils/CommonUtils.java rename to src/main/java/com/gmh/utils/StringUtils.java index 99b5b69..6f21e18 100644 --- a/src/main/java/com/gmh/utils/CommonUtils.java +++ b/src/main/java/com/gmh/utils/StringUtils.java @@ -1,6 +1,8 @@ package com.gmh.utils; -public class CommonUtils { +import cn.hutool.core.util.StrUtil; + +public class StringUtils extends StrUtil { public static String nameFormat(String name) { StringBuilder newName = new StringBuilder(name.replaceAll("\\s*", "")); diff --git a/src/main/java/com/gmh/utils/ThrowableUtil.java b/src/main/java/com/gmh/utils/ThrowableUtil.java new file mode 100644 index 0000000..c26224e --- /dev/null +++ b/src/main/java/com/gmh/utils/ThrowableUtil.java @@ -0,0 +1,23 @@ +package com.gmh.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class ThrowableUtil { + + /** + * 获取堆栈信息 + * @param throwable + * @return + */ + public static String getStackTrace(Throwable throwable){ + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + try { + throwable.printStackTrace(pw); + return sw.toString(); + } finally { + pw.close(); + } + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a779b5b..1127e63 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,3 +13,13 @@ gmh.upload-path="C:/develop/projUpload #???????? spring.servlet.multipart.max-file-size=31457280 spring.servlet.multipart.max-request-size=31457280 + +data.file-server.type: local +#oss?? +data.file-server.oss.access-key: tpi8mObnfzZi4ggBX8Bw7zydjoTQ0WeML3RkPKsX +data.file-server.oss.access-key-secret: HZBXmSyUTy-haYp0KbBTtsil-GoKjVS2kDKT8Yow +data.file-server.oss.bucket-name: public-oss +data.file-server.oss.domain-name: http://pkqtmn0p1.bkt.clouddn.com +#local?? +data.file-server.local.path: C:\\develop\\uploadfile +data.file-server.local.prefix: fileView \ No newline at end of file