<!-- 導出word文檔所需依賴--><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.0-beta</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>4.1.2</version></dependency><!-- 導出word文檔所需依賴--><!-- word轉pdf 依賴--><dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.0.3</version></dependency><dependency><groupId>com.documents4j</groupId><artifactId>documents4j-transformer-msoffice-word</artifactId><version>1.0.3</version></dependency><!-- word轉pdf 依賴-->
代碼
// 導出報告 word文檔 模板類型 正式節點才能導出報告@GetMapping("/exportReportWord")@ApiOperationSupport(order = 8)@ApiOperation(value = "導出報告 PDF 文檔", notes = "")public void exportReportWord(@RequestParam String ids, HttpServletResponse response) throws IOException {List<CmComplaintEntity> joints = cmComplaintService.listByIds(Func.toStrList(ids));String uuid = UUID.randomUUID().toString();Path zipPath = Paths.get(pathProperties.getReport(), uuid + ".zip");File zipFile = zipPath.toFile();if (zipFile.exists()) {zipFile.delete(); // 如果文件存在則先刪除舊的文件}List<File> pdfFiles = null;try {if (!zipFile.getParentFile().exists()) {Files.createDirectories(zipPath.getParent());}pdfFiles = joints.stream().map(joint -> {String fileName = joint.getWorkOrderNo();Path docxPath = Paths.get(pathProperties.getReport(), uuid, fileName + ".docx");Path pdfPath = Paths.get(pathProperties.getReport(), uuid, fileName + ".pdf");File docxFile = docxPath.toFile();File pdfFile = pdfPath.toFile();try {if (!docxFile.getParentFile().exists()) {Files.createDirectories(docxPath.getParent());}if (!docxFile.exists()) {Files.createFile(docxPath);}// 生成 Word 文檔XWPFTemplate template = getXwpfTemplate(joint);try (FileOutputStream fos = new FileOutputStream(docxFile)) {template.write(fos);}// 轉換 Word 到 PDFif (docxFile.exists()) {convertWordToPdf(docxFile, pdfFile);}} catch (Exception e) {e.printStackTrace();}return pdfFile;}).collect(Collectors.toList());// 壓縮 PDF 文件ZipUtil.zipFile(pdfFiles, zipPath.toFile().getAbsolutePath());} catch (Exception e) {e.printStackTrace();} finally {if (pdfFiles != null) {for (File f : pdfFiles) {if (f.exists()) {f.delete();}}}Path dirPath = Paths.get(pathProperties.getReport(), uuid);if (dirPath.toFile().exists()) {dirPath.toFile().delete();}}// 下載文件InputStream inStream = null;try {if (!zipFile.exists()) {return;}inStream = new FileInputStream(zipFile);response.reset();response.setContentType("application/zip");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFile.getName(), "UTF-8"));response.setCharacterEncoding("UTF-8");IoUtil.copy(inStream, response.getOutputStream());} catch (Exception e) {e.printStackTrace();} finally {if (inStream != null) {try {inStream.close();} catch (IOException e) {e.printStackTrace();}}if (zipFile.exists()) {zipFile.delete(); // 壓縮包也刪除}}}/*** 傳入 節點對象 返回生成的word文檔* @param flangeJoint* @return* @throws IOException*/private XWPFTemplate getXwpfTemplate(CmComplaintEntity flangeJoint) throws IOException {Map<String, Object> map = new HashMap<>();
// List<Map<String, Object>> table = this.setListData(flangeJoints); 無內循環表格
// map.put("table", table);map.put("jointNo", "123");// 導出PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();Resource resource = resolver.getResource("classpath:/templates/jointReport_en.docx");
// Configure config = Configure.builder().bind("table", new LoopRowTableRenderPolicy()).build();
// XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream(), config).render(map);XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream()).render(map);return template;}/*** 將Word文件轉換為PDF文件* @param wordFile Word文件* @param pdfFile PDF文件*/public void convertWordToPdf(File wordFile, File pdfFile) {try (InputStream docxInputStream = new FileInputStream(wordFile);OutputStream outputStream = new FileOutputStream(pdfFile)) {IConverter converter = LocalConverter.builder().build();converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();System.out.println("Word轉PDF成功: " + wordFile.getName());} catch (Exception e) {e.printStackTrace();System.err.println("Word轉PDF失敗: " + wordFile.getName() + ", 錯誤: " + e.getMessage());}}
如果是直接生成word的話,用下面的代碼:
// 導出報告 word文檔 模板類型 正式節點才能導出報告@GetMapping("/exportReportWord")@ApiOperationSupport(order = 8)@ApiOperation(value = "導出報告 PDF 文檔", notes = "")public void exportReportWord(@RequestParam String ids, HttpServletResponse response) throws IOException {List<CmComplaintEntity> joints = cmComplaintService.listByIds(Func.toStrList(ids));String uuid = UUID.randomUUID().toString();Path zipPath = Paths.get(pathProperties.getReport(), uuid + ".zip");File zipFile = zipPath.toFile();if (zipFile.exists()) {zipFile.delete(); // 如果文件存在則先刪除舊的文件}List<File> pdfFiles = null;try {if (!zipFile.getParentFile().exists()) {Files.createDirectories(zipPath.getParent());}pdfFiles = joints.stream().map(joint -> {String fileName = joint.getWorkOrderNo();Path docxPath = Paths.get(pathProperties.getReport(), uuid, fileName + ".docx");Path pdfPath = Paths.get(pathProperties.getReport(), uuid, fileName + ".pdf");File docxFile = docxPath.toFile();File pdfFile = pdfPath.toFile();try {if (!docxFile.getParentFile().exists()) {Files.createDirectories(docxPath.getParent());}if (!docxFile.exists()) {Files.createFile(docxPath);}// 生成 Word 文檔XWPFTemplate template = getXwpfTemplate(joint);try (FileOutputStream fos = new FileOutputStream(docxFile)) {template.write(fos);}// 轉換 Word 到 PDFif (docxFile.exists()) {convertWordToPdf(docxFile, pdfFile);}} catch (Exception e) {e.printStackTrace();}return pdfFile;}).collect(Collectors.toList());// 壓縮 PDF 文件ZipUtil.zipFile(pdfFiles, zipPath.toFile().getAbsolutePath());} catch (Exception e) {e.printStackTrace();} finally {if (pdfFiles != null) {for (File f : pdfFiles) {if (f.exists()) {f.delete();}}}Path dirPath = Paths.get(pathProperties.getReport(), uuid);if (dirPath.toFile().exists()) {dirPath.toFile().delete();}}// 下載文件InputStream inStream = null;try {if (!zipFile.exists()) {return;}inStream = new FileInputStream(zipFile);response.reset();response.setContentType("application/zip");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFile.getName(), "UTF-8"));response.setCharacterEncoding("UTF-8");IoUtil.copy(inStream, response.getOutputStream());} catch (Exception e) {e.printStackTrace();} finally {if (inStream != null) {try {inStream.close();} catch (IOException e) {e.printStackTrace();}}if (zipFile.exists()) {zipFile.delete(); // 壓縮包也刪除}}}/*** 傳入 節點對象 返回生成的word文檔* @param flangeJoint* @return* @throws IOException*/private XWPFTemplate getXwpfTemplate(CmComplaintEntity flangeJoint) throws IOException {Map<String, Object> map = new HashMap<>();
// List<Map<String, Object>> table = this.setListData(flangeJoints); 無內循環表格
// map.put("table", table);map.put("jointNo", "123");// 導出PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();Resource resource = resolver.getResource("classpath:/templates/jointReport_en.docx");
// Configure config = Configure.builder().bind("table", new LoopRowTableRenderPolicy()).build();
// XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream(), config).render(map);XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream()).render(map);return template;}/*** 將Word文件轉換為PDF文件* @param wordFile Word文件* @param pdfFile PDF文件*/public void convertWordToPdf(File wordFile, File pdfFile) {try (InputStream docxInputStream = new FileInputStream(wordFile);OutputStream outputStream = new FileOutputStream(pdfFile)) {IConverter converter = LocalConverter.builder().build();converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();System.out.println("Word轉PDF成功: " + wordFile.getName());} catch (Exception e) {e.printStackTrace();System.err.println("Word轉PDF失敗: " + wordFile.getName() + ", 錯誤: " + e.getMessage());}}
下面有一個依賴的工具類?
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;import java.io.File;
import java.nio.charset.Charset;
import java.util.List;public class ZipUtil {public static void zipFile(File dir, String file) throws ZipException {// 生成的壓縮文件ZipFile zipFile = new ZipFile(file);ZipParameters parameters = new ZipParameters();// 壓縮方式parameters.setCompressionMethod(CompressionMethod.DEFLATE);// 壓縮級別parameters.setCompressionLevel(CompressionLevel.FAST);// 要打包的文件夾File[] list = dir.listFiles();// 遍歷文件夾下所有的文件、文件夾for (File f: list) {if (f.isDirectory()) {zipFile.addFile(f.getPath(), parameters);} else {zipFile.addFile(f, parameters);}}}public static void zipFile(List<File> list, String file) throws ZipException {// 生成的壓縮文件ZipFile zipFile = new ZipFile(file);ZipParameters parameters = new ZipParameters();// 壓縮方式parameters.setCompressionMethod(CompressionMethod.STORE);// 壓縮級別parameters.setCompressionLevel(CompressionLevel.FAST);// 遍歷文件夾下所有的文件、文件夾for (File f: list) {if (f.isDirectory()) {zipFile.addFile(f.getPath(), parameters);} else {zipFile.addFile(f, parameters);}}}public static void unzip(String srcFile, String destDir) throws Exception {/** 判斷文件是否存在 */File file = new File(srcFile);if (file.exists()) {ZipFile zipFile = new ZipFile(srcFile);// 設置編碼格式中文設置為GBK格式zipFile.setCharset(Charset.forName("GBK"));// 解壓壓縮包zipFile.extractAll(destDir);}}}
這個工具類依賴于
<!-- zip --><dependency><groupId>net.lingala.zip4j</groupId><artifactId>zip4j</artifactId><version>2.7.0</version></dependency>
本文介紹了一個基于Java的文檔處理方案,主要實現Word文檔生成和PDF轉換功能。系統使用poi-tl和Apache POI庫生成Word文檔,通過documents4j實現Word轉PDF,并采用zip4j進行文件壓縮。核心功能包括:1)根據模板動態生成Word文檔;2)將Word批量轉換為PDF;3)將多個PDF文件打包下載。代碼展示了完整的文檔處理流程,包括文件創建、格式轉換、壓縮打包和下載清理等操作,同時提供了異常處理和資源清理機制。該方案適用于需要批量生成和導出報告文檔的業務場景。