Commit 5958d0b9f675718bbc4ad931493ae69944730ccd

Authored by yeqianyong
1 parent 2d757cc3

楚江erp:样品反馈单导出功能开发(支持PDF)

@@ -35,6 +35,9 @@ import org.springframework.validation.annotation.Validated; @@ -35,6 +35,9 @@ import org.springframework.validation.annotation.Validated;
35 import org.springframework.web.bind.annotation.*; 35 import org.springframework.web.bind.annotation.*;
36 36
37 import javax.validation.Valid; 37 import javax.validation.Valid;
  38 +import java.io.File;
  39 +import java.io.FileInputStream;
  40 +import java.io.FileOutputStream;
38 import java.io.InputStream; 41 import java.io.InputStream;
39 import java.time.format.DateTimeFormatter; 42 import java.time.format.DateTimeFormatter;
40 import java.util.ArrayList; 43 import java.util.ArrayList;
@@ -113,7 +116,7 @@ public class SampleResultFeedbackController extends DefaultBaseController { @@ -113,7 +116,7 @@ public class SampleResultFeedbackController extends DefaultBaseController {
113 */ 116 */
114 @ApiOperation("规格变更打印") 117 @ApiOperation("规格变更打印")
115 @GetMapping("/export") 118 @GetMapping("/export")
116 - public void export(@NotBlank(message = "id不能为空") String id, @NotBlank(message = "导出类型不能为空") String exportType 119 + public void export(@NotBlank(message = "id不能为空") String id, String exportType
117 , HttpServletResponse response) { 120 , HttpServletResponse response) {
118 SampleResultFeedback data = sampleResultFeedbackService.findById(id); 121 SampleResultFeedback data = sampleResultFeedbackService.findById(id);
119 if (data == null) { 122 if (data == null) {
@@ -123,7 +126,6 @@ public class SampleResultFeedbackController extends DefaultBaseController { @@ -123,7 +126,6 @@ public class SampleResultFeedbackController extends DefaultBaseController {
123 try (InputStream inputStream = templateResource.getStream(); 126 try (InputStream inputStream = templateResource.getStream();
124 Workbook workbook = new XSSFWorkbook(inputStream)) { 127 Workbook workbook = new XSSFWorkbook(inputStream)) {
125 Sheet sheet = workbook.getSheetAt(0); 128 Sheet sheet = workbook.getSheetAt(0);
126 - ResponseUtil.setExcelResponseHead(response, data.getOrderNo() + "-试样结果反馈单.xlsx");  
127 DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 129 DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
128 List<SampleFeedbackTrackingDetail> detailList = data.getDetailList(); 130 List<SampleFeedbackTrackingDetail> detailList = data.getDetailList();
129 // ========== 起始行:5========== 131 // ========== 起始行:5==========
@@ -174,8 +176,25 @@ public class SampleResultFeedbackController extends DefaultBaseController { @@ -174,8 +176,25 @@ public class SampleResultFeedbackController extends DefaultBaseController {
174 176
175 ExcelUtil.processTemplate(workbook, dataMap); 177 ExcelUtil.processTemplate(workbook, dataMap);
176 if ("PDF".equals(exportType)) { 178 if ("PDF".equals(exportType)) {
  179 + ResponseUtil.setPDFResponseHead(response, data.getOrderNo() + "-试样结果反馈单.xlsx");
177 // 输出为PDF文档 180 // 输出为PDF文档
  181 + // === 写入临时 .xls 文件 ===
  182 + File tempExcel = File.createTempFile("sample_feedback_" + data.getOrderNo(), ".xls");
  183 + try (FileOutputStream fos = new FileOutputStream(tempExcel)) {
  184 + workbook.write(fos);
  185 + }
  186 + File pdfFile = ExcelUtil.convertExcelToPdf(tempExcel, "/usr/bin/libreoffice --headless --convert-to pdf --outdir %s %s");
  187 + // === 输出 PDF 到浏览器 ===
  188 + try (InputStream pdfIn = new FileInputStream(pdfFile)) {
  189 + byte[] buffer = new byte[8192];
  190 + int len;
  191 + while ((len = pdfIn.read(buffer)) != -1) {
  192 + response.getOutputStream().write(buffer, 0, len);
  193 + }
  194 + response.getOutputStream().flush();
  195 + }
178 } else { 196 } else {
  197 + ResponseUtil.setExcelResponseHead(response, data.getOrderNo() + "-试样结果反馈单.xlsx");
179 // 输出 198 // 输出
180 workbook.write(response.getOutputStream()); 199 workbook.write(response.getOutputStream());
181 response.getOutputStream().flush(); 200 response.getOutputStream().flush();
@@ -6,12 +6,15 @@ import org.apache.poi.ss.util.CellRangeAddress; @@ -6,12 +6,15 @@ import org.apache.poi.ss.util.CellRangeAddress;
6 6
7 import javax.swing.*; 7 import javax.swing.*;
8 import java.awt.*; 8 import java.awt.*;
  9 +import java.io.File;
  10 +import java.io.IOException;
9 import java.math.BigDecimal; 11 import java.math.BigDecimal;
10 import java.time.LocalDate; 12 import java.time.LocalDate;
11 import java.time.format.DateTimeFormatter; 13 import java.time.format.DateTimeFormatter;
12 import java.util.ArrayList; 14 import java.util.ArrayList;
13 import java.util.List; 15 import java.util.List;
14 import java.util.Map; 16 import java.util.Map;
  17 +import java.util.concurrent.TimeUnit;
15 18
16 @Slf4j 19 @Slf4j
17 public class ExcelUtil { 20 public class ExcelUtil {
@@ -240,4 +243,39 @@ public class ExcelUtil { @@ -240,4 +243,39 @@ public class ExcelUtil {
240 // 设置样式 243 // 设置样式
241 cell.setCellStyle(style); 244 cell.setCellStyle(style);
242 } 245 }
  246 +
  247 +
  248 + /**
  249 + * EXCEL转成PDF
  250 + *
  251 + * @param excelFile EXCEL文件
  252 + * @return File
  253 + */
  254 + public static File convertExcelToPdf(File excelFile, String path) throws IOException, InterruptedException {
  255 + if (!excelFile.exists()) {
  256 + throw new IllegalArgumentException("Excel 文件不存在: " + excelFile.getAbsolutePath());
  257 + }
  258 + String pdfPath = excelFile.getAbsolutePath().replaceAll("\\.xls$", ".pdf");
  259 + File pdfFile = new File(pdfPath);
  260 + // 使用绝对路径 /usr/bin/libreoffice(CentOS 7 默认位置)
  261 + String command = String.format(
  262 + path,
  263 + excelFile.getParent(),
  264 + excelFile.getAbsolutePath()
  265 + );
  266 + Process process = Runtime.getRuntime().exec(command);
  267 + boolean finished = process.waitFor(30, TimeUnit.SECONDS); // 超时 30 秒
  268 + if (!finished) {
  269 + process.destroyForcibly();
  270 + throw new RuntimeException("LibreOffice 转换超时(>30秒)");
  271 + }
  272 + int exitCode = process.exitValue();
  273 + if (exitCode != 0) {
  274 + throw new RuntimeException("LibreOffice 转换失败,退出码: " + exitCode);
  275 + }
  276 + if (!pdfFile.exists()) {
  277 + throw new RuntimeException("PDF 未生成: " + pdfPath);
  278 + }
  279 + return pdfFile;
  280 + }
243 } 281 }
@@ -42,4 +42,16 @@ public class ResponseUtil { @@ -42,4 +42,16 @@ public class ResponseUtil {
42 } 42 }
43 43
44 44
  45 + /**
  46 + * 设置HTTP响应头
  47 + * pdf
  48 + */
  49 + public static void setPDFResponseHead(HttpServletResponse response, String fileName) throws IOException {
  50 + String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  51 +
  52 + response.setContentType("application/pdf");
  53 + response.setCharacterEncoding("UTF-8");
  54 + response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
  55 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
  56 + }
45 } 57 }