diff --git a/src/main/java/com/sipai/activiti/util/DateConverter.java b/src/main/java/com/sipai/activiti/util/DateConverter.java index 6803f6da..810e0987 100644 --- a/src/main/java/com/sipai/activiti/util/DateConverter.java +++ b/src/main/java/com/sipai/activiti/util/DateConverter.java @@ -28,7 +28,7 @@ public class DateConverter implements Converter { try { result = doConvertToDate(value); } catch (ParseException e) { - e.printStackTrace(); + logger.error("Failed to convert value to Date: " + value, e); } } else if (type == String.class) { result = doConvertToString(value); @@ -56,8 +56,7 @@ public class DateConverter implements Converter { try { result = new Date(new Long((String) value).longValue()); } catch (Exception e) { - logger.error("Converting from milliseconds to Date fails!"); - e.printStackTrace(); + logger.error("Converting from milliseconds to Date fails!", e); } } diff --git a/src/main/java/com/sipai/controller/accident/AccidentController.java b/src/main/java/com/sipai/controller/accident/AccidentController.java index ecd8ba3f..feb720f8 100644 --- a/src/main/java/com/sipai/controller/accident/AccidentController.java +++ b/src/main/java/com/sipai/controller/accident/AccidentController.java @@ -12,6 +12,8 @@ import com.sipai.service.accident.AccidentTypeService; import com.sipai.service.user.UnitService; import com.sipai.tools.CommUtil; import net.sf.json.JSONArray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; @@ -26,6 +28,7 @@ import java.util.List; @Controller @RequestMapping("/accident/accident") public class AccidentController { + private static final Logger logger = LoggerFactory.getLogger(AccidentController.class); @Resource private AccidentService accidentService; @Resource @@ -174,7 +177,7 @@ public class AccidentController { this.accidentService.deleteById(idArray[i]); } } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to delete accidents with ids: {}", ids, e); Result result = Result.failed("删除失败"); model.addAttribute("result", CommUtil.toJson(result)); return "result"; diff --git a/src/main/java/com/sipai/controller/accident/ReasonableAdviceController.java b/src/main/java/com/sipai/controller/accident/ReasonableAdviceController.java index 9cbb8d6d..5a844e0c 100644 --- a/src/main/java/com/sipai/controller/accident/ReasonableAdviceController.java +++ b/src/main/java/com/sipai/controller/accident/ReasonableAdviceController.java @@ -28,6 +28,8 @@ import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; @@ -45,6 +47,7 @@ import java.util.*; @Controller @RequestMapping("/accident/reasonableAdvice") public class ReasonableAdviceController { + private static final Logger logger = LoggerFactory.getLogger(ReasonableAdviceController.class); @Resource private ReasonableAdviceService reasonableAdviceService; @Resource @@ -211,7 +214,7 @@ public class ReasonableAdviceController { this.reasonableAdviceService.deleteById(idArray[i]); } } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to delete reasonable advices with ids: {}", ids, e); Result result = Result.failed("删除失败"); model.addAttribute("result", CommUtil.toJson(result)); return "result"; @@ -302,10 +305,10 @@ public class ReasonableAdviceController { wherestr += " and take_flag = '"+request.getParameter("takeFlag")+"' "; } List list = this.reasonableAdviceService.selectListByWhere(wherestr+orderstr); - try { + try { this.reasonableAdviceService.downloadExcel(response,list); } catch (IOException e) { - e.printStackTrace(); + logger.error("Failed to download excel for reasonable advice", e); } return null; } @@ -325,8 +328,7 @@ public class ReasonableAdviceController { try { result =this.reasonableAdviceService.startProcess(reasonableAdvice); } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); + logger.error("Failed to start process for reasonable advice: {}", reasonableAdvice.getId(), e); } String resstr="{\"res\":\""+result+"\",\"id\":\""+reasonableAdvice.getId()+"\"}"; model.addAttribute("result", resstr); @@ -403,7 +405,7 @@ public class ReasonableAdviceController { return 0; } }catch(Exception e){ - e.printStackTrace(); + logger.error("Failed to compare business unit records", e); return 0; } @@ -588,8 +590,7 @@ public class ReasonableAdviceController { } this.reasonableAdviceService.updateStatus(businessUnitHandle.getBusinessid(),passstatus); } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); + logger.error("Failed to submit reasonable advice handle: {}", businessUnitHandle.getId(), e); result=0; } String resstr="{\"res\":\""+result+"\",\"id\":\""+businessUnitHandle.getId()+"\"}"; diff --git a/src/main/java/com/sipai/controller/accident/RoastController.java b/src/main/java/com/sipai/controller/accident/RoastController.java index ba523564..ac74d622 100644 --- a/src/main/java/com/sipai/controller/accident/RoastController.java +++ b/src/main/java/com/sipai/controller/accident/RoastController.java @@ -28,6 +28,8 @@ import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; @@ -45,6 +47,7 @@ import java.util.*; @Controller @RequestMapping("/accident/roast") public class RoastController { + private static final Logger logger = LoggerFactory.getLogger(RoastController.class); @Resource private RoastService roastService; @Resource @@ -249,7 +252,7 @@ public class RoastController { this.roastService.deleteById(idArray[i]); } } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to delete roasts with ids: {}", ids, e); Result result = Result.failed("删除失败"); model.addAttribute("result", CommUtil.toJson(result)); return "result"; @@ -345,7 +348,7 @@ public class RoastController { try { this.roastService.downloadExcel(response, list); } catch (IOException e) { - e.printStackTrace(); + logger.error("Failed to download excel for roast", e); } return null; } @@ -367,8 +370,7 @@ public class RoastController { try { result = this.roastService.startProcess(roast); } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); + logger.error("Failed to start process for roast: {}", roast.getId(), e); } String resstr = "{\"res\":\"" + result + "\",\"id\":\"" + roast.getId() + "\"}"; model.addAttribute("result", resstr); @@ -447,7 +449,7 @@ public class RoastController { return 0; } } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to compare business unit records", e); return 0; } @@ -636,8 +638,7 @@ public class RoastController { } this.roastService.updateStatus(businessUnitHandle.getBusinessid(), passstatus); } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); + logger.error("Failed to submit roast handle: {}", businessUnitHandle.getId(), e); result = 0; } String resstr = "{\"res\":\"" + result + "\",\"id\":\"" + businessUnitHandle.getId() + "\"}"; diff --git a/src/main/java/com/sipai/controller/achievement/AcceptanceModelController.java b/src/main/java/com/sipai/controller/achievement/AcceptanceModelController.java index 559c76f8..f508f843 100644 --- a/src/main/java/com/sipai/controller/achievement/AcceptanceModelController.java +++ b/src/main/java/com/sipai/controller/achievement/AcceptanceModelController.java @@ -17,6 +17,8 @@ import com.sipai.service.user.UserService; import com.sipai.tools.CommUtil; import net.sf.json.JSONObject; import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; @@ -39,6 +41,7 @@ import java.util.Map; @Controller @RequestMapping("/achievement/acceptanceModel") public class AcceptanceModelController { + private static final Logger logger = LoggerFactory.getLogger(AcceptanceModelController.class); @Resource private AcceptanceModelService acceptanceModelService; @Resource @@ -262,7 +265,7 @@ public class AcceptanceModelController { file.mkdir(); } }catch (Exception e){ - e.printStackTrace(); + logger.error("Failed to create directory for file conversion: {}", fileforder, e); } //开始生成 @@ -291,8 +294,8 @@ public class AcceptanceModelController { } else { ret.put("suc", false); } - } catch (Exception e) { - e.printStackTrace(); + } catch (Exception e) { + logger.error("Failed to upload file for acceptance model", e); ret.put("suc", false); ret.put("msg", e.getMessage()); } diff --git a/src/main/java/com/sipai/controller/achievement/AcceptanceModelCreateController.java b/src/main/java/com/sipai/controller/achievement/AcceptanceModelCreateController.java index 9f925a42..657af8d1 100644 --- a/src/main/java/com/sipai/controller/achievement/AcceptanceModelCreateController.java +++ b/src/main/java/com/sipai/controller/achievement/AcceptanceModelCreateController.java @@ -24,6 +24,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @@ -51,6 +53,7 @@ import static org.apache.poi.ss.usermodel.CellType.STRING; @Controller @RequestMapping("/achievement/acceptanceModelCreate") public class AcceptanceModelCreateController { + private static final Logger logger = LoggerFactory.getLogger(AcceptanceModelCreateController.class); @Resource private AcceptanceModelService acceptanceModelService; @Resource @@ -747,7 +750,7 @@ public class AcceptanceModelCreateController { file.mkdir(); } }catch (Exception e){ - e.printStackTrace(); + logger.error("Failed to create directory for file conversion: {}", fileforder, e); } //开始生成 diff --git a/src/main/java/com/sipai/controller/activiti/ActivitiController.java b/src/main/java/com/sipai/controller/activiti/ActivitiController.java index c897ac3d..f061da49 100644 --- a/src/main/java/com/sipai/controller/activiti/ActivitiController.java +++ b/src/main/java/com/sipai/controller/activiti/ActivitiController.java @@ -95,6 +95,8 @@ import javax.servlet.http.HttpServletResponse; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -332,9 +334,9 @@ public class ActivitiController { try {//解决中文乱码问题 wherestr_search_name=new String(wherestr_search_name.getBytes("ISO-8859-1"),"UTF-8"); wherestr_search_code=new String(wherestr_search_code.getBytes("ISO-8859-1"),"UTF-8"); - } catch (UnsupportedEncodingException e) + } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + logger.error("Failed to encode search parameters", e); } // Page page1 = new Page(PageUtil.PAGE_SIZE); // int[] pageParams = PageUtil.init(page1, request); @@ -1034,8 +1036,7 @@ public class ActivitiController { } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); + logger.error("Failed to process todo task", e); } } @@ -1079,7 +1080,7 @@ public class ActivitiController { valA = a.getString(KEY_NAME); valB = b.getString(KEY_NAME); } catch (JSONException e) { - e.printStackTrace(); + logger.error("Failed to get JSON key: {}", KEY_NAME, e); } //是升序还是降序 if (is_desc){ @@ -1448,9 +1449,8 @@ public class ActivitiController { repositoryService.deleteDeployment(deploymentId, true); result=1; } catch (Exception e) { - // TODO: handle exception + logger.error("Failed to delete deployment: {}", deploymentId, e); result =0; - e.printStackTrace(); } model.addAttribute("result", result); @@ -1466,9 +1466,8 @@ public class ActivitiController { runtimeService.deleteProcessInstance(processInstanceId,""); result=1; } catch (Exception e) { - // TODO: handle exception + logger.error("Failed to delete process instance: {}", processInstanceId, e); result =0; - e.printStackTrace(); } model.addAttribute("result", result); @@ -1490,7 +1489,7 @@ public class ActivitiController { try{ activityInfos = traceService.traceProcess(processInstanceId,taskId); }catch(Exception e){ - e.printStackTrace(); + logger.error("Failed to trace process: {}", processInstanceId, e); } return activityInfos; } @@ -1508,7 +1507,7 @@ public class ActivitiController { try{ activityInfos = traceService.traceProcessByDefinitionId(processDefinitionId); }catch(Exception e){ - e.printStackTrace(); + logger.error("Failed to trace process definition: {}", processDefinitionId, e); } return "/activiti/processDefinitionTrace"; } @@ -1571,6 +1570,139 @@ public class ActivitiController { return "redirect:/workflow/process-list"; } + /** + * 部署diagrams文件夹下的所有BPMN文件 + * 支持批量部署指定目录下的流程定义 + * + * @param folderName 文件夹名称(如: leave, dispatch等),为空则部署所有 + * @return 部署结果 + */ + @RequestMapping(value = "/deployDiagrams.do") + public String deployDiagrams(HttpServletRequest request, Model model, + @RequestParam(value = "folderName", required = false) String folderName) { + int successCount = 0; + int failCount = 0; + JSONArray resultArray = new JSONArray(); + + try { + // 获取diagrams目录路径 + String diagramsPath = request.getSession().getServletContext() + .getRealPath("/WEB-INF/classes/diagrams"); + if (diagramsPath == null) { + diagramsPath = this.getClass().getClassLoader() + .getResource("diagrams").getPath(); + } + + File diagramsDir = new File(diagramsPath); + if (!diagramsDir.exists() || !diagramsDir.isDirectory()) { + model.addAttribute("result", "{\"res\":\"0\",\"msg\":\"diagrams目录不存在\"}"); + return "result"; + } + + // 获取需要部署的文件夹列表 + List targetDirs = new ArrayList(); + if (folderName != null && !folderName.isEmpty()) { + File targetDir = new File(diagramsDir, folderName); + if (targetDir.exists() && targetDir.isDirectory()) { + targetDirs.add(targetDir); + } + } else { + // 部署所有子文件夹 + File[] subDirs = diagramsDir.listFiles(File::isDirectory); + if (subDirs != null) { + targetDirs.addAll(java.util.Arrays.asList(subDirs)); + } + } + + // 遍历部署每个文件夹下的BPMN文件 + for (File dir : targetDirs) { + File[] bpmnFiles = dir.listFiles((d, name) -> + name.endsWith(".bpmn") || name.endsWith(".bpmn20.xml")); + + if (bpmnFiles == null || bpmnFiles.length == 0) { + continue; + } + + for (File bpmnFile : bpmnFiles) { + try { + String fileName = bpmnFile.getName(); + FileInputStream fis = new FileInputStream(bpmnFile); + + Deployment deployment = repositoryService.createDeployment() + .name(fileName.substring(0, fileName.lastIndexOf("."))) + .addInputStream(fileName, fis) + .deploy(); + + fis.close(); + + JSONObject deployResult = new JSONObject(); + deployResult.put("fileName", fileName); + deployResult.put("deploymentId", deployment.getId()); + deployResult.put("deploymentName", deployment.getName()); + deployResult.put("deploymentTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .format(deployment.getDeploymentTime())); + resultArray.add(deployResult); + successCount++; + + logger.info("流程部署成功: {} -> {}", fileName, deployment.getId()); + } catch (Exception e) { + failCount++; + logger.error("流程部署失败: {}", bpmnFile.getName(), e); + } + } + } + + } catch (Exception e) { + logger.error("部署diagrams文件失败", e); + model.addAttribute("result", "{\"res\":\"0\",\"msg\":\"" + e.getMessage() + "\"}"); + return "result"; + } + + String result = "{\"res\":\"1\",\"success\":" + successCount + ",\"fail\":" + failCount + + ",\"deployments\":" + resultArray.toString() + "}"; + model.addAttribute("result", result); + return "result"; + } + + /** + * 获取diagrams目录下可部署的BPMN文件列表 + */ + @RequestMapping(value = "/getDeployableBpmnFiles.do") + public String getDeployableBpmnFiles(HttpServletRequest request, Model model) { + JSONArray filesArray = new JSONArray(); + + try { + String diagramsPath = this.getClass().getClassLoader() + .getResource("diagrams").getPath(); + File diagramsDir = new File(diagramsPath); + + if (diagramsDir.exists() && diagramsDir.isDirectory()) { + File[] subDirs = diagramsDir.listFiles(File::isDirectory); + if (subDirs != null) { + for (File dir : subDirs) { + File[] bpmnFiles = dir.listFiles((d, name) -> + name.endsWith(".bpmn") || name.endsWith(".bpmn20.xml")); + + if (bpmnFiles != null) { + for (File bpmnFile : bpmnFiles) { + JSONObject fileInfo = new JSONObject(); + fileInfo.put("folder", dir.getName()); + fileInfo.put("fileName", bpmnFile.getName()); + fileInfo.put("filePath", "diagrams/" + dir.getName() + "/" + bpmnFile.getName()); + filesArray.add(fileInfo); + } + } + } + } + } + } catch (Exception e) { + logger.error("获取BPMN文件列表失败", e); + } + + model.addAttribute("result", filesArray.toString()); + return "result"; + } + @RequestMapping(value = "/process/convert-to-model/{processDefinitionId}") public String convertToModel(@PathVariable("processDefinitionId") String processDefinitionId) throws UnsupportedEncodingException, XMLStreamException { @@ -1710,7 +1842,7 @@ public class ActivitiController { taskService.claim(taskId, userId); result=1; }catch(Exception e){ - e.printStackTrace(); + logger.error("Failed to claim task: {}", taskId, e); } model.addAttribute("result", result); @@ -1734,7 +1866,7 @@ public class ActivitiController { try{ taskService.claim(taskId, userId); }catch(Exception e){ - e.printStackTrace(); + logger.error("Failed to claim task in batch: {}", taskId, e); continue; } result++; diff --git a/src/main/java/com/sipai/controller/data/DataCurveController.java b/src/main/java/com/sipai/controller/data/DataCurveController.java index 116e6c71..88dff5a9 100644 --- a/src/main/java/com/sipai/controller/data/DataCurveController.java +++ b/src/main/java/com/sipai/controller/data/DataCurveController.java @@ -1732,13 +1732,21 @@ public class DataCurveController { name = curveRemarkFile.getFilename(); } byte[] bytes = commonFileService.getInputStreamBytes("curve", path); + if (bytes == null || bytes.length == 0) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件不存在或已被删除"; + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + return; + } InputStream object = new ByteArrayInputStream(bytes); byte buf[] = new byte[1024]; int length = 0; - String fileName = new String(name.getBytes(), "ISO-8859-1");//压缩包中文名称,不然乱码 + // 使用UTF-8编码处理中文文件名 + String encodedFileName = java.net.URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20"); response.reset(); - response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName); response.setContentType("application/octet-stream"); response.setCharacterEncoding("UTF-8"); OutputStream outputStream = response.getOutputStream(); diff --git a/src/main/java/com/sipai/controller/report/RptCreateController.java b/src/main/java/com/sipai/controller/report/RptCreateController.java index c11e4d6c..3ccd0762 100644 --- a/src/main/java/com/sipai/controller/report/RptCreateController.java +++ b/src/main/java/com/sipai/controller/report/RptCreateController.java @@ -709,9 +709,9 @@ public class RptCreateController { if (rptInfoSetFile != null) { try { String path = rptInfoSetFile.getAbspath(); - path = path.replaceAll(".xls", ""); - path = path.replaceAll(".xlsx", ""); - String base = this.rptCreateService.convertExceltoHtml(CommUtil.fixRptCreateFileName(path), sheetname, id, layerType, FileNameSpaceEnum.RptInfoSetFile.getNameSpace()); +// path = path.replaceAll("\\.xlsx", "").replaceAll("\\.xls", ""); +// String base = this.rptCreateService.convertExceltoHtml(CommUtil.fixRptCreateFileName(path), sheetname, id, layerType, FileNameSpaceEnum.RptInfoSetFile.getNameSpace()); + String base = this.rptCreateService.convertExceltoHtml(path, sheetname, id, layerType, FileNameSpaceEnum.RptInfoSetFile.getNameSpace()); //截取掉sheet名 目前只能先截取h2 String result = subRangeString(base, "

", "

"); result = result.replaceAll("", "
"); @@ -755,30 +755,18 @@ public class RptCreateController { if (rptCreate != null) {//报表生成中的预览 List list = rptInfoSetSheetService.selectListByWhere("where rptInfoSet_id = '" + rptCreate.getRptsetId() + "'"); try { - String sourcePath = ""; + String sourcePath = rptCreate.getRptname(); byte[] isb = commonFileService.getInputStreamBytes(FileNameSpaceEnum.RptCreateFile.getNameSpace(), CommUtil.fixRptCreateFileName(rptCreate.getRptname() + rptCreate.getId())); - InputStream is = new ByteArrayInputStream(isb); - String sheets = ""; - if (sourcePath.indexOf(".xlsx") > 0) { - XSSFWorkbook workBook = new XSSFWorkbook(is); - for (int i = 0; i < workBook.getNumberOfSheets(); i++) { - XSSFSheet sheet = workBook.getSheetAt(i); - sheets += sheet.getSheetName() + ","; - } - } else { - HSSFWorkbook workBook = new HSSFWorkbook(is); - for (int i = 0; i < workBook.getNumberOfSheets(); i++) { - HSSFSheet sheet = workBook.getSheetAt(i); - sheets += sheet.getSheetName() + ","; - } - } - for (RptInfoSetSheet entity : list) { - sheets = sheets.replace(entity.getSheetName() + ",", ""); + if (isb == null || isb.length == 0) { + result1 = Result_Report.failed("文件不存在或已被删除"); + model.addAttribute("result", CommUtil.toJson(result1)); + return "result"; } + String sheets = getString(isb, sourcePath, list); result1 = Result_Report.success(Result.SUCCESS, sheets); } catch (Exception e) { e.printStackTrace(); - result1 = Result_Report.failed("获取失败"); + result1 = Result_Report.failed("获取失败: " + e.getMessage()); } } else {//报表配置中的预览 RptInfoSetFile rptInfoSetFile = rptInfoSetFileService.selectById(id); @@ -787,31 +775,36 @@ public class RptCreateController { try { String sourcePath = ""; String path = rptInfoSetFile.getAbspath(); - path = path.replaceAll(".xls", ""); - path = path.replaceAll(".xlsx", ""); - byte[] isb = commonFileService.getInputStreamBytes(FileNameSpaceEnum.RptInfoSetFile.getNameSpace(), CommUtil.fixRptCreateFileName(path)); +// path = path.replaceAll("\\.xlsx", "").replaceAll("\\.xls", ""); +// byte[] isb = commonFileService.getInputStreamBytes(FileNameSpaceEnum.RptInfoSetFile.getNameSpace(), CommUtil.fixRptCreateFileName(path)); + byte[] isb = commonFileService.getInputStreamBytes(FileNameSpaceEnum.RptInfoSetFile.getNameSpace(), path); + if (isb == null || isb.length == 0) { + result1 = Result_Report.failed("文件不存在或已被删除,请重新上传模板文件"); + model.addAttribute("result", CommUtil.toJson(result1)); + return "result"; + } InputStream is = new ByteArrayInputStream(isb); - String sheets = ""; - if (sourcePath.indexOf(".xlsx") > 0) { + StringBuilder sheets = new StringBuilder(); + if (path.indexOf(".xlsx") > 0) { XSSFWorkbook workBook = new XSSFWorkbook(is); for (int i = 0; i < workBook.getNumberOfSheets(); i++) { XSSFSheet sheet = workBook.getSheetAt(i); - sheets += sheet.getSheetName() + ","; + sheets.append(sheet.getSheetName()).append(","); } } else { HSSFWorkbook workBook = new HSSFWorkbook(is); for (int i = 0; i < workBook.getNumberOfSheets(); i++) { HSSFSheet sheet = workBook.getSheetAt(i); - sheets += sheet.getSheetName() + ","; + sheets.append(sheet.getSheetName()).append(","); } } for (RptInfoSetSheet entity : list) { - sheets = sheets.replace(entity.getSheetName() + ",", ""); + sheets = new StringBuilder(sheets.toString().replace(entity.getSheetName() + ",", "")); } - result1 = Result_Report.success(Result.SUCCESS, sheets); + result1 = Result_Report.success(Result.SUCCESS, sheets.toString()); } catch (Exception e) { e.printStackTrace(); - result1 = Result_Report.failed("获取失败"); + result1 = Result_Report.failed("获取失败: " + e.getMessage()); } } } @@ -819,6 +812,28 @@ public class RptCreateController { return "result"; } + private static String getString(byte[] isb, String sourcePath, List list) throws IOException { + InputStream is = new ByteArrayInputStream(isb); + StringBuilder sheets = new StringBuilder(); + if (sourcePath.indexOf(".xlsx") > 0) { + XSSFWorkbook workBook = new XSSFWorkbook(is); + for (int i = 0; i < workBook.getNumberOfSheets(); i++) { + XSSFSheet sheet = workBook.getSheetAt(i); + sheets.append(sheet.getSheetName()).append(","); + } + } else { + HSSFWorkbook workBook = new HSSFWorkbook(is); + for (int i = 0; i < workBook.getNumberOfSheets(); i++) { + HSSFSheet sheet = workBook.getSheetAt(i); + sheets.append(sheet.getSheetName()).append(","); + } + } + for (RptInfoSetSheet entity : list) { + sheets = new StringBuilder(sheets.toString().replace(entity.getSheetName() + ",", "")); + } + return sheets.toString(); + } + /** * 报表下载 * @@ -839,13 +854,21 @@ public class RptCreateController { name = rptCreate.getRptname() + ".xls"; } byte[] bytes = commonFileService.getInputStreamBytes(FileNameSpaceEnum.RptCreateFile.getNameSpace(), path); + if (bytes == null || bytes.length == 0) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件不存在或已被删除"; + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + return; + } InputStream object = new ByteArrayInputStream(bytes); byte buf[] = new byte[1024]; int length = 0; - String fileName = new String(name.getBytes(), "ISO-8859-1");//压缩包中文名称,不然乱码 + // 使用UTF-8编码处理中文文件名 + String encodedFileName = java.net.URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20"); response.reset(); - response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName); response.setContentType("application/octet-stream"); response.setCharacterEncoding("UTF-8"); OutputStream outputStream = response.getOutputStream(); @@ -1219,6 +1242,7 @@ public class RptCreateController { /** * 获取单个 报表详情 + * * @param request * @param model * @return diff --git a/src/main/java/com/sipai/controller/report/RptInfoSetFileController.java b/src/main/java/com/sipai/controller/report/RptInfoSetFileController.java index 8dbeadaa..61c3fab0 100644 --- a/src/main/java/com/sipai/controller/report/RptInfoSetFileController.java +++ b/src/main/java/com/sipai/controller/report/RptInfoSetFileController.java @@ -178,13 +178,22 @@ public class RptInfoSetFileController { } } + if (bytes == null || bytes.length == 0) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件不存在或已被删除"; + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + return; + } + InputStream object = new ByteArrayInputStream(bytes); byte buf[] = new byte[1024]; int length = 0; - String fileName = new String(name.getBytes(), "ISO-8859-1");//压缩包中文名称,不然乱码 + // 使用UTF-8编码处理中文文件名 + String encodedFileName = java.net.URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20"); response.reset(); - response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName); response.setContentType("application/octet-stream"); response.setCharacterEncoding("UTF-8"); OutputStream outputStream = response.getOutputStream(); diff --git a/src/main/java/com/sipai/controller/user/MenuController.java b/src/main/java/com/sipai/controller/user/MenuController.java index 91739bb0..4fa9b756 100644 --- a/src/main/java/com/sipai/controller/user/MenuController.java +++ b/src/main/java/com/sipai/controller/user/MenuController.java @@ -38,6 +38,9 @@ public class MenuController { public String showMenuListByCu(HttpServletRequest request,Model model){ User cu= (User)request.getSession().getAttribute("cu"); List list = this.menuService.getFullPower(cu.getId()); +// if("emp01".equals(cu.getId())){ +// list = menuService.selectListByWhere(" where 1=1 "); +// } if(list!=null &&list.size()>0){ for(int i=list.size()-1;i>=0;i--){ Menu menu=list.get(i); diff --git a/src/main/java/com/sipai/controller/work/CameraController.java b/src/main/java/com/sipai/controller/work/CameraController.java index ac7f99e3..e8480dfe 100644 --- a/src/main/java/com/sipai/controller/work/CameraController.java +++ b/src/main/java/com/sipai/controller/work/CameraController.java @@ -754,13 +754,21 @@ public class CameraController { name = cameraFile.getFilename(); } byte[] bytes = commonFileService.getInputStreamBytes("cameraimg", path); + if (bytes == null || bytes.length == 0) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件不存在或已被删除"; + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + return; + } InputStream object = new ByteArrayInputStream(bytes); byte buf[] = new byte[1024]; int length = 0; - String fileName = new String(name.getBytes(), "ISO-8859-1");//压缩包中文名称,不然乱码 + // 使用UTF-8编码处理中文文件名 + String encodedFileName = java.net.URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20"); response.reset(); - response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName); response.setContentType("application/octet-stream"); response.setCharacterEncoding("UTF-8"); OutputStream outputStream = response.getOutputStream(); diff --git a/src/main/java/com/sipai/entity/activiti/ProcessType.java b/src/main/java/com/sipai/entity/activiti/ProcessType.java index 48fb475c..7b6cf881 100644 --- a/src/main/java/com/sipai/entity/activiti/ProcessType.java +++ b/src/main/java/com/sipai/entity/activiti/ProcessType.java @@ -97,7 +97,7 @@ public enum ProcessType { } public static String getName(String id) { - for (PatrolType item :PatrolType.values()) { + for (ProcessType item :ProcessType.values()) { if (item.getId().equals(id)) { return item.getName(); } @@ -106,7 +106,7 @@ public enum ProcessType { } public static JSONArray toJson() { JSONArray jsonArray = new JSONArray(); - for (PatrolType item :PatrolType.values()) { + for (ProcessType item :ProcessType.values()) { JSONObject jsonObject = new JSONObject(); jsonObject.put("id", item.getId()); jsonObject.put("name", item.getName()); diff --git a/src/main/java/com/sipai/service/base/CommonFileServiceImpl.java b/src/main/java/com/sipai/service/base/CommonFileServiceImpl.java index 809ededf..e8f1646e 100644 --- a/src/main/java/com/sipai/service/base/CommonFileServiceImpl.java +++ b/src/main/java/com/sipai/service/base/CommonFileServiceImpl.java @@ -16,6 +16,8 @@ import com.sipai.service.user.UserService; import com.sipai.tools.CommUtil; import com.sipai.tools.FileUtil; import io.minio.ObjectStat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -24,12 +26,88 @@ import javax.annotation.Resource; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; @Service public class CommonFileServiceImpl implements CommonFileService { + + private static final Logger logger = LoggerFactory.getLogger(CommonFileServiceImpl.class); + + /** + * Safely get the original filename with proper UTF-8 encoding + * Detects whether ISO-8859-1 to UTF-8 conversion is needed + * + * @param item the MultipartFile + * @return properly encoded filename + */ + private String getSafeFileName(MultipartFile item) { + String fileName = item.getOriginalFilename(); + if (fileName == null || fileName.isEmpty()) { + return "unknown_file"; + } + + // Check if filename contains garbled characters (likely ISO-8859-1 encoded) + // If the filename contains replacement characters or mojibake, try to convert + try { + // Check if already valid UTF-8 (contains Chinese or other UTF-8 characters) + byte[] bytes = fileName.getBytes("UTF-8"); + String reconstructed = new String(bytes, "UTF-8"); + + // If the string contains '?' that weren't originally there, it might need conversion + // Try ISO-8859-1 to UTF-8 conversion only if the string looks like it needs it + boolean needsConversion = false; + + // Check if filename contains typical mojibake patterns (like '???' for Chinese) + // or if it's clearly Latin-1 encoded + if (fileName.contains("???") || fileName.contains("Ã") || fileName.contains("Â")) { + needsConversion = true; + } else { + // Try to detect if the bytes look like UTF-8 bytes incorrectly interpreted as ISO-8859-1 + try { + String testConvert = new String(fileName.getBytes("ISO-8859-1"), "UTF-8"); + // If conversion produces valid Chinese characters where there were none, use converted version + if (testConvert.matches(".*[\u4e00-\u9fa5].*") && !fileName.matches(".*[\u4e00-\u9fa5].*")) { + fileName = testConvert; + } + } catch (Exception e) { + // Conversion failed, keep original + } + } + } catch (UnsupportedEncodingException e) { + // Keep original filename + } + + return fileName; + } + + /** + * Generate a MinIO-safe object name from original filename + * Uses timestamp + UUID to ensure ASCII-only, unique object names + * MinIO Java client handles URL encoding internally, so we must NOT pre-encode + * + * @param originalFileName the original filename (can contain Chinese/special chars) + * @param timestamp timestamp prefix for uniqueness + * @return MinIO-safe object name (ASCII only) + */ + private String generateMinioObjectName(String originalFileName, String timestamp) { + // Extract file extension + String extension = ""; + int dotIndex = originalFileName.lastIndexOf('.'); + if (dotIndex > 0 && dotIndex < originalFileName.length() - 1) { + extension = originalFileName.substring(dotIndex); + } + + // Generate a safe ASCII-only object name using timestamp + UUID + // Do NOT use URL encoding as MinIO client will encode again internally + // This avoids double-encoding issues + String uuid = CommUtil.getUUID().replace("-", "").substring(0, 8); + + return timestamp + "-" + uuid + extension; + } + @Resource private CommonFileDao commonFileDao; @Resource @@ -256,11 +334,10 @@ public class CommonFileServiceImpl implements CommonFileService { //minio @Override public byte[] getInputStreamBytes(String nameSpace, String filePath) { - byte[] buffer = null; + byte[] buffer = new byte[0]; try { ObjectStat stat = minioTemplate.statObject(nameSpace, filePath); InputStream in = minioTemplate.getObject(nameSpace, filePath); - in = minioTemplate.getObject(nameSpace, filePath); ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[(int) stat.length()]; //buff用于存放循环读取的临时数据 int rc = 0; @@ -270,7 +347,13 @@ public class CommonFileServiceImpl implements CommonFileService { buffer = swapStream.toByteArray(); //in_b为转换之后的结果 in.close(); } catch (Exception e) { - e.printStackTrace(); + // MinIO错误:文件不存在等情况 + String errorMsg = e.getMessage(); + if (errorMsg != null && errorMsg.contains("NoSuchKey")) { + logger.error("MinIO文件不存在: bucketName={}, objectName={}", nameSpace, filePath); + } else { + logger.error("获取MinIO文件失败: bucketName={}, objectName={}, 错误: {}", nameSpace, filePath, errorMsg, e); + } } return buffer; } @@ -286,13 +369,18 @@ public class CommonFileServiceImpl implements CommonFileService { */ @Transactional public int updateFile(String masterId, String nameSpace, String tableName, MultipartFile item) { - String fileName = ""; //文件名称 - String filePath = ""; //文件存储名称,相同名称在minio中会被覆盖掉 + String fileName = ""; //文件名称(原始名称,用于显示) + String filePath = ""; //文件存储名称(MinIO对象名称),相同名称在minio中会被覆盖掉 int res = 0; try { - fileName = item.getOriginalFilename(); + // 安全获取文件名(自动检测编码) + fileName = getSafeFileName(item); + + // 生成MinIO安全的对象名称 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); - filePath = dateFormat.format(new Date()) + fileName; + String timestamp = dateFormat.format(new Date()); + filePath = generateMinioObjectName(fileName, timestamp); + InputStream in = item.getInputStream(); String contentType = item.getContentType(); minioTemplate.makeBucket(nameSpace); @@ -303,16 +391,16 @@ public class CommonFileServiceImpl implements CommonFileService { commonFile.setMasterid(masterId); // 20210105 YYJ 用于文件表绑定资料节点用字段 tb_doc_file内和masterId一样 // commonFile.setPid(masterId); - commonFile.setFilename(fileName); + commonFile.setFilename(fileName); // 保存原始文件名用于显示 commonFile.setType(contentType); //minio用相对路径 // commonFile.setFilepath(filePath); - commonFile.setAbspath(filePath); + commonFile.setAbspath(filePath); // 保存MinIO对象名称 commonFile.setInsdt(CommUtil.nowDate()); commonFile.setSize((int) item.getSize()); res = this.insertByTable(tableName, commonFile); } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to update file to MinIO for masterId: {}", masterId, e); throw new RuntimeException(); } return res; @@ -328,18 +416,19 @@ public class CommonFileServiceImpl implements CommonFileService { */ @Transactional public int updateFile_creat(String masterId, String nameSpace, String tableName, MultipartFile item, String uuid) { - String fileName = ""; //文件名称 - String filePath = ""; //文件存储名称,相同名称在minio中会被覆盖掉 + String fileName = ""; //文件名称(原始名称,用于显示) + String filePath = ""; //文件存储名称(MinIO对象名称),相同名称在minio中会被覆盖掉 int res = 0; try { - fileName = item.getOriginalFilename(); -// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); -// filePath = dateFormat.format(new Date()) + fileName; + // 安全获取文件名(自动检测编码) + fileName = getSafeFileName(item); fileName = fileName.replace(".xls", ""); fileName = fileName.replace(".xlsx", ""); - filePath = fileName + uuid + ".xls"; + // 生成MinIO安全的对象名称:使用uuid(ASCII only) + // 不要使用URL编码,MinIO客户端会再次编码导致双重编码问题 + filePath = uuid + ".xls"; InputStream in = item.getInputStream(); String contentType = item.getContentType(); @@ -351,16 +440,16 @@ public class CommonFileServiceImpl implements CommonFileService { commonFile.setMasterid(masterId); // 20210105 YYJ 用于文件表绑定资料节点用字段 tb_doc_file内和masterId一样 // commonFile.setPid(masterId); - commonFile.setFilename(fileName); + commonFile.setFilename(fileName); // 保存原始文件名用于显示 commonFile.setType(contentType); //minio用相对路径 // commonFile.setFilepath(filePath); - commonFile.setAbspath(filePath); + commonFile.setAbspath(filePath); // 保存MinIO对象名称 commonFile.setInsdt(CommUtil.nowDate()); commonFile.setSize((int) item.getSize()); res = this.insertByTable(tableName, commonFile); } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to update file (creat) to MinIO for masterId: {}", masterId, e); throw new RuntimeException(); } return res; @@ -376,13 +465,31 @@ public class CommonFileServiceImpl implements CommonFileService { */ @Transactional public int updateFileForFileIn(String masterId, String nameSpace, String tableName, FileIn item) { - String fileName = ""; //文件名称 - String filePath = ""; //文件存储名称,相同名称在minio中会被覆盖掉 + String fileName = ""; //文件名称(原始名称,用于显示) + String filePath = ""; //文件存储名称(MinIO对象名称),相同名称在minio中会被覆盖掉 int res = 0; try { + // 安全获取文件名(自动检测编码) fileName = item.getOriginalFilename(); + if (fileName == null || fileName.isEmpty()) { + fileName = "unknown_file"; + } else { + // 检测是否需要进行ISO-8859-1到UTF-8的转换 + try { + String testConvert = new String(fileName.getBytes("ISO-8859-1"), "UTF-8"); + if (testConvert.matches(".*[\u4e00-\u9fa5].*") && !fileName.matches(".*[\u4e00-\u9fa5].*")) { + fileName = testConvert; + } + } catch (Exception e) { + // 转换失败,保持原文件名 + } + } + + // 生成MinIO安全的对象名称 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); - filePath = dateFormat.format(new Date()) + fileName; + String timestamp = dateFormat.format(new Date()); + filePath = generateMinioObjectName(fileName, timestamp); + InputStream in = item.getInputStream(); String contentType = item.getContentType(); minioTemplate.makeBucket(nameSpace); @@ -393,16 +500,16 @@ public class CommonFileServiceImpl implements CommonFileService { commonFile.setMasterid(masterId); // 20210105 YYJ 用于文件表绑定资料节点用字段 tb_doc_file内和masterId一样 // commonFile.setPid(masterId); - commonFile.setFilename(fileName); + commonFile.setFilename(fileName); // 保存原始文件名用于显示 commonFile.setType(contentType); //minio用相对路径 // commonFile.setFilepath(filePath); - commonFile.setAbspath(filePath); + commonFile.setAbspath(filePath); // 保存MinIO对象名称 commonFile.setInsdt(CommUtil.nowDate()); commonFile.setSize((int) item.getSize()); res = this.insertByTable(tableName, commonFile); } catch (Exception e) { - e.printStackTrace(); + logger.error("Failed to update file (FileIn) to MinIO for masterId: {}", masterId, e); throw new RuntimeException(); } return res; diff --git a/src/main/java/com/sipai/service/base/MinioTemplate.java b/src/main/java/com/sipai/service/base/MinioTemplate.java index d368945c..70fbcac6 100644 --- a/src/main/java/com/sipai/service/base/MinioTemplate.java +++ b/src/main/java/com/sipai/service/base/MinioTemplate.java @@ -5,6 +5,8 @@ import io.minio.ObjectStat; import io.minio.ServerSideEncryption; import io.minio.errors.*; import io.minio.messages.Bucket; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.xmlpull.v1.XmlPullParserException; @@ -18,8 +20,29 @@ import java.util.Map; @Service public class MinioTemplate { + + private static final Logger logger = LoggerFactory.getLogger(MinioTemplate.class); + @Resource private MinioClient minioClient; + + /** + * 测试MinIO服务是否可用 + * @return true-可用 false-不可用 + */ + public boolean testConnection() { + try { + minioClient.listBuckets(); + logger.info("MinIO连接测试成功"); + return true; + } catch (InvalidResponseException e) { + logger.error("MinIO连接失败: 收到非XML响应。请检查配置的端口是否正确(应为S3 API端口9000,而非Console端口9001)。错误信息: {}", e.getMessage()); + return false; + } catch (Exception e) { + logger.error("MinIO连接失败: {}。请确认MinIO服务已启动,配置的endpoint地址和端口正确。", e.getMessage()); + return false; + } + } /** * 检查文件存储桶是否存在 @@ -27,7 +50,12 @@ public class MinioTemplate { * @return */ public boolean bucketExists(String bucketName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, InvalidResponseException, IOException, XmlPullParserException{ - return minioClient.bucketExists(bucketName); + try { + return minioClient.bucketExists(bucketName); + } catch (InvalidResponseException e) { + logger.error("MinIO bucketExists失败: 收到非XML响应。请检查配置的端口是否正确(应为S3 API端口9000,而非Console端口9001)。bucketName: {}", bucketName); + throw e; + } } /** @@ -36,9 +64,15 @@ public class MinioTemplate { * @param bucketName bucket名称 */ public void makeBucket(String bucketName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, InvalidResponseException, RegionConflictException, IOException, XmlPullParserException { - if (!bucketExists(bucketName)) { - minioClient.makeBucket(bucketName); - } + try { + if (!bucketExists(bucketName)) { + minioClient.makeBucket(bucketName); + logger.info("成功创建MinIO存储桶: {}", bucketName); + } + } catch (InvalidResponseException e) { + logger.error("MinIO makeBucket失败: 收到非XML响应。请检查配置的端口是否正确(应为S3 API端口9000,而非Console端口9001)。bucketName: {}", bucketName); + throw e; + } } /** @@ -97,11 +131,12 @@ public class MinioTemplate { * @param objectName 文件名称 * @param stream 文件流 * @param size 大小 - * @param contextType 类型 + * @param contentType 类型 */ public void putObject(String bucketName, String objectName, InputStream stream, Long size, Map headerMap, ServerSideEncryption sse, String contentType) throws Exception { minioClient.putObject(bucketName,objectName,stream,size, headerMap, sse, contentType); + logger.debug("文件上传成功: bucketName={}, objectName={}", bucketName, objectName); } /** diff --git a/src/main/java/com/sipai/service/report/impl/RptCreateServiceImpl.java b/src/main/java/com/sipai/service/report/impl/RptCreateServiceImpl.java index 2109e705..38de0e21 100644 --- a/src/main/java/com/sipai/service/report/impl/RptCreateServiceImpl.java +++ b/src/main/java/com/sipai/service/report/impl/RptCreateServiceImpl.java @@ -249,7 +249,7 @@ public class RptCreateServiceImpl implements RptCreateService { converter.setOutputRowNumbers(false);// 不显示行的表头 //重新创建workbook - HSSFWorkbook wb = CreatNewWorkBook(sheet, sheetname, id, layerType); + HSSFWorkbook wb = CreatNewWorkBook(sheet, sheetname, id, layerType, workBook); converter.processWorkbook(wb); writer = new StringWriter(); @@ -283,7 +283,7 @@ public class RptCreateServiceImpl implements RptCreateService { converter.setOutputColumnHeaders(false);// 不显示列的表头 converter.setOutputRowNumbers(false);// 不显示行的表头 //重新创建workbook - HSSFWorkbook wb = CreatNewWorkBook(sheet, sheetname, id, layerType); + HSSFWorkbook wb = CreatNewWorkBook(sheet, sheetname, id, layerType, workBook); converter.processWorkbook(wb); writer = new StringWriter(); Transformer serializer = TransformerFactory.newInstance().newTransformer(); @@ -397,7 +397,7 @@ public class RptCreateServiceImpl implements RptCreateService { return list; } - private HSSFWorkbook CreatNewWorkBook(Sheet sheet, String sheetname, String id, String layerType) throws IOException { + private HSSFWorkbook CreatNewWorkBook(Sheet sheet, String sheetname, String id, String layerType, Workbook sourceWorkbook) throws IOException { // Drawing draw = sheet.createDrawingPatriarch();//初始化批注 // Comment comment = draw.createCellComment(new HSSFClientAnchor()); // comment.setString(new HSSFRichTextString("请在平台上查看备注"));//设置批注内容 @@ -458,15 +458,15 @@ public class RptCreateServiceImpl implements RptCreateService { cellStyle = wbCreat.createCellStyle(); List int1 = getMergedRegionValue(sheetCreat, i, j); - if (int1 != null && int1.size() > 0) { + if (!int1.isEmpty()) { for (int k = int1.get(0); k <= int1.get(1); k++) { if (row.getCell(k) != null && !row.getCell(k).equals("")) { - cellStyle.cloneStyleFrom(row.getCell(k).getCellStyle()); + copyCellStyle(wbCreat, cellStyle, row.getCell(k).getCellStyle(), sourceWorkbook); rowCreat.createCell(k).setCellStyle(cellStyle); } } } else { - cellStyle.cloneStyleFrom(row.getCell(j).getCellStyle()); + copyCellStyle(wbCreat, cellStyle, row.getCell(j).getCellStyle(), sourceWorkbook); rowCreat.createCell(j).setCellStyle(cellStyle); } @@ -482,13 +482,13 @@ public class RptCreateServiceImpl implements RptCreateService { break; case NUMERIC: cellStyle = wbCreat.createCellStyle(); - cellStyle.cloneStyleFrom(row.getCell(j).getCellStyle()); + copyCellStyle(wbCreat, cellStyle, row.getCell(j).getCellStyle(), sourceWorkbook); rowCreat.createCell(j).setCellStyle(cellStyle); rowCreat.getCell(j).setCellValue(row.getCell(j).getNumericCellValue()); break; case FORMULA: cellStyle = wbCreat.createCellStyle(); - cellStyle.cloneStyleFrom(row.getCell(j).getCellStyle()); + copyCellStyle(wbCreat, cellStyle, row.getCell(j).getCellStyle(), sourceWorkbook); rowCreat.createCell(j).setCellStyle(cellStyle); //此处为字体大小样式 不需要 注释即可 // cellStyle.setFont(headfont); @@ -501,8 +501,7 @@ public class RptCreateServiceImpl implements RptCreateService { /** * 下面为获取excle中的小数位 */ - HSSFCellStyle hssVal = (HSSFCellStyle) row.getCell(j).getCellStyle(); - String excelValStyle = hssVal.getDataFormatString(); + String excelValStyle = row.getCell(j).getCellStyle().getDataFormatString(); if (excelValStyle != null && excelValStyle.contains("_")) { String result = excelValStyle; if (excelValStyle.contains("[Red]")) { @@ -560,7 +559,7 @@ public class RptCreateServiceImpl implements RptCreateService { break; default: cellStyle = wbCreat.createCellStyle(); - cellStyle.cloneStyleFrom(row.getCell(j).getCellStyle()); + copyCellStyle(wbCreat, cellStyle, row.getCell(j).getCellStyle(), sourceWorkbook); rowCreat.createCell(j).setCellStyle(cellStyle); } } @@ -580,6 +579,75 @@ public class RptCreateServiceImpl implements RptCreateService { return wbCreat; } + /** + * Copy cell style from source (HSSF or XSSF) to target HSSF cell style + * This method manually copies style properties to avoid the + * "Can only clone from one HSSFCellStyle to another" error + * + * @param wbCreat the target HSSFWorkbook + * @param targetStyle the target HSSFCellStyle to copy to + * @param sourceStyle the source CellStyle (can be HSSFCellStyle or XSSFCellStyle) + * @param sourceWorkbook the source Workbook (can be HSSFWorkbook or XSSFWorkbook) + */ + private void copyCellStyle(HSSFWorkbook wbCreat, HSSFCellStyle targetStyle, CellStyle sourceStyle, Workbook sourceWorkbook) { + try { + // Copy alignment + targetStyle.setAlignment(sourceStyle.getAlignment()); + targetStyle.setVerticalAlignment(sourceStyle.getVerticalAlignment()); + + // Copy border + targetStyle.setBorderBottom(sourceStyle.getBorderBottom()); + targetStyle.setBorderLeft(sourceStyle.getBorderLeft()); + targetStyle.setBorderRight(sourceStyle.getBorderRight()); + targetStyle.setBorderTop(sourceStyle.getBorderTop()); + + // Copy border colors + targetStyle.setBottomBorderColor(sourceStyle.getBottomBorderColor()); + targetStyle.setLeftBorderColor(sourceStyle.getLeftBorderColor()); + targetStyle.setRightBorderColor(sourceStyle.getRightBorderColor()); + targetStyle.setTopBorderColor(sourceStyle.getTopBorderColor()); + + // Copy fill + targetStyle.setFillBackgroundColor(sourceStyle.getFillBackgroundColor()); + targetStyle.setFillForegroundColor(sourceStyle.getFillForegroundColor()); + targetStyle.setFillPattern(sourceStyle.getFillPattern()); + + // Copy data format + if (sourceStyle.getDataFormatString() != null) { + DataFormat dataFormat = wbCreat.createDataFormat(); + targetStyle.setDataFormat(dataFormat.getFormat(sourceStyle.getDataFormatString())); + } + + // Copy font - get font from source workbook and create equivalent in target workbook + try { + Font sourceFont = sourceWorkbook.getFontAt(sourceStyle.getFontIndex()); + if (sourceFont != null) { + Font newFont = wbCreat.createFont(); + newFont.setFontName(sourceFont.getFontName()); + newFont.setFontHeightInPoints(sourceFont.getFontHeightInPoints()); + newFont.setBold(sourceFont.getBold()); + newFont.setItalic(sourceFont.getItalic()); + newFont.setUnderline(sourceFont.getUnderline()); + newFont.setColor(sourceFont.getColor()); + targetStyle.setFont(newFont); + } + } catch (Exception fontEx) { + // If font copy fails, use default font + } + + // Copy other properties + targetStyle.setHidden(sourceStyle.getHidden()); + targetStyle.setLocked(sourceStyle.getLocked()); + targetStyle.setWrapText(sourceStyle.getWrapText()); + targetStyle.setIndention(sourceStyle.getIndention()); + targetStyle.setRotation(sourceStyle.getRotation()); + + } catch (Exception e) { + // If style copy fails, just use default style + // This prevents the entire process from failing + } + } + /** * excel97中颜色转化为uof颜色 * diff --git a/src/main/java/com/sipai/service/report/impl/RptLogServiceImpl.java b/src/main/java/com/sipai/service/report/impl/RptLogServiceImpl.java index 8f02b8ec..6d311ff0 100644 --- a/src/main/java/com/sipai/service/report/impl/RptLogServiceImpl.java +++ b/src/main/java/com/sipai/service/report/impl/RptLogServiceImpl.java @@ -118,8 +118,8 @@ public class RptLogServiceImpl implements RptLogService { /* * 传到minio */ + String rptname = path.replaceAll("\\.xlsx", "").replaceAll("\\.xls", ""); try { - String rptname = path.replaceAll(".xls", ""); String showname = rptname; InputStream stream = null; //获取类加载的根路径 diff --git a/src/main/java/com/sipai/service/safety/SafetyFilesService.java b/src/main/java/com/sipai/service/safety/SafetyFilesService.java index 4d1e7697..73267c5d 100644 --- a/src/main/java/com/sipai/service/safety/SafetyFilesService.java +++ b/src/main/java/com/sipai/service/safety/SafetyFilesService.java @@ -250,7 +250,9 @@ public class SafetyFilesService implements CommService { int len = 0; byte[] buffer = new byte[1024]; ServletOutputStream out = response.getOutputStream(); - response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(file.getOriginalFileName(), "UTF-8")); + // 使用UTF-8编码处理中文文件名 + String encodedFileName = URLEncoder.encode(file.getOriginalFileName(), "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName); response.getOutputStream(); while ((len = input.read(buffer)) > 0) { out.write(buffer, 0, len); diff --git a/src/main/resources/minio.properties b/src/main/resources/minio.properties index 4da921f8..1ad209c4 100644 --- a/src/main/resources/minio.properties +++ b/src/main/resources/minio.properties @@ -1,3 +1,13 @@ -minio.endPoint=http://122.51.194.184:19000 -minio.accessKey=minio -minio.secretKey=BHwChyGLt8FkaA7H +#minio.endPoint=http://122.51.194.184:19000 +#minio.accessKey=minio +#minio.secretKey=BHwChyGLt8FkaA7H + +# MinIO配置说明: +# - 端口9000: S3 API端口(程序访问使用此端口) +# - 端口9001: Console端口(Web管理界面) +# 请确保MinIO服务已启动,并根据实际情况修改endpoint地址 + +# 本地开发环境配置 +minio.endPoint=http://127.0.0.1:9000 +minio.accessKey=minioadmin +minio.secretKey=minioadmin diff --git a/src/main/resources/mqtt.properties b/src/main/resources/mqtt.properties index fa49baf9..9135a32e 100644 --- a/src/main/resources/mqtt.properties +++ b/src/main/resources/mqtt.properties @@ -2,11 +2,11 @@ #\u9879\u76EE\u662F\u5426\u4F7F\u7528mqtt 0\uFF1A\u542F\u52A8 1\uFF1A\u7981\u7528 mqtt.status=0 #tcp -mqtt.host_tcp=tcp://127.0.0.1:1883 +mqtt.host_tcp=tcp://122.51.194.184:1883 #websocket -mqtt.host_ws=ws://127.0.0.1:8083/mqtt +mqtt.host_ws=ws://122.51.194.184:8083/mqtt #http -mqtt.host_http=http://127.0.0.1:18083 +mqtt.host_http=http://122.51.194.184:18083 #\u00E7\u0094\u00A8\u00E6\u0088\u00B7\u00E5\u0090\u008D mqtt.username=dmbroker #\u00E5\u00AF\u0086\u00E7\u00A0\u0081