Commit 5958d0b9f675718bbc4ad931493ae69944730ccd

Authored by yeqianyong
1 parent 2d757cc3

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

... ... @@ -35,6 +35,9 @@ import org.springframework.validation.annotation.Validated;
35 35 import org.springframework.web.bind.annotation.*;
36 36
37 37 import javax.validation.Valid;
  38 +import java.io.File;
  39 +import java.io.FileInputStream;
  40 +import java.io.FileOutputStream;
38 41 import java.io.InputStream;
39 42 import java.time.format.DateTimeFormatter;
40 43 import java.util.ArrayList;
... ... @@ -113,7 +116,7 @@ public class SampleResultFeedbackController extends DefaultBaseController {
113 116 */
114 117 @ApiOperation("规格变更打印")
115 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 120 , HttpServletResponse response) {
118 121 SampleResultFeedback data = sampleResultFeedbackService.findById(id);
119 122 if (data == null) {
... ... @@ -123,7 +126,6 @@ public class SampleResultFeedbackController extends DefaultBaseController {
123 126 try (InputStream inputStream = templateResource.getStream();
124 127 Workbook workbook = new XSSFWorkbook(inputStream)) {
125 128 Sheet sheet = workbook.getSheetAt(0);
126   - ResponseUtil.setExcelResponseHead(response, data.getOrderNo() + "-试样结果反馈单.xlsx");
127 129 DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
128 130 List<SampleFeedbackTrackingDetail> detailList = data.getDetailList();
129 131 // ========== 起始行:5==========
... ... @@ -174,8 +176,25 @@ public class SampleResultFeedbackController extends DefaultBaseController {
174 176
175 177 ExcelUtil.processTemplate(workbook, dataMap);
176 178 if ("PDF".equals(exportType)) {
  179 + ResponseUtil.setPDFResponseHead(response, data.getOrderNo() + "-试样结果反馈单.xlsx");
177 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 196 } else {
  197 + ResponseUtil.setExcelResponseHead(response, data.getOrderNo() + "-试样结果反馈单.xlsx");
179 198 // 输出
180 199 workbook.write(response.getOutputStream());
181 200 response.getOutputStream().flush();
... ...
... ... @@ -6,12 +6,15 @@ import org.apache.poi.ss.util.CellRangeAddress;
6 6
7 7 import javax.swing.*;
8 8 import java.awt.*;
  9 +import java.io.File;
  10 +import java.io.IOException;
9 11 import java.math.BigDecimal;
10 12 import java.time.LocalDate;
11 13 import java.time.format.DateTimeFormatter;
12 14 import java.util.ArrayList;
13 15 import java.util.List;
14 16 import java.util.Map;
  17 +import java.util.concurrent.TimeUnit;
15 18
16 19 @Slf4j
17 20 public class ExcelUtil {
... ... @@ -240,4 +243,39 @@ public class ExcelUtil {
240 243 // 设置样式
241 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 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 }
... ...