赞
踩
由于最近做了一个需求,界面上有一个按钮,点击按钮后将一个文件夹中的word文档显示在页面中,并且有一个下拉框可以选择不同的文档,选择文档可以显示该文档。这里我选择使用fr.opensagres.poi.xwpf.converter.pdf-gae
依赖包来实现。
这里我只依赖了这些依赖包
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
<version>2.0.1</version>
</dependency>
<!-- Apache PDFBox 依赖用于.docx转PDF -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.0</version> <!-- 根据最新版本调整 -->
</dependency>
Java代码部分,这里我使用了两个文件夹中的文档
package com.hxgis.controller; import java.io.File; import java.io.FileInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter; import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; import org.springframework.http.ResponseEntity; import org.apache.poi.xwpf.usermodel.XWPFDocument; //import org.apache.poi.xwpf.converter.pdf.PdfOptions; //import org.apache.poi.xwpf.converter.pdf.PdfConverter; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * ClassName: DocumentController * Package: com.hxgis.controller * Description: * * @Author dhn * @Create 2024/1/31 11:56 * @Version 1.0 */ @RestController @RequestMapping("/api/document") public class DocumentController { private final String MONTH_PATH = "D:/ftp_data/month"; // 修改为你的文档存储路径 private final String QUARTER_PATH = "D:/ftp_data/quarter"; // 修改为你的文档存储路径 // private final String MONTH_PATH = "/home/geli/hbnyWeatherReport/month"; // 修改为你的文档存储路径 // private final String QUARTER_PATH = "/home/geli/hbnyWeatherReport/quarter"; // 修改为你的文档存储路径 @GetMapping("/monthLatest") public ResponseEntity<Resource> getDocument(@RequestParam(required = false) String name) throws IOException { File folder = new File(MONTH_PATH); File[] files = folder.listFiles((dir, filename) -> filename.endsWith(".docx")); if (files == null || files.length == 0) { return ResponseEntity.notFound().build(); } File fileToConvert; if (name != null && !name.isEmpty()) { // 用户选择了特定的文件 fileToConvert = Arrays.stream(files) .filter(file -> file.getName().equals(name)) .findFirst() .orElse(null); } else { // 没有特定选择,找最新的文件 Pattern pattern = Pattern.compile("(\\d{4})年(\\d{2})月风光资源趋势预测\\.docx"); fileToConvert = Arrays.stream(files) .filter(file -> pattern.matcher(file.getName()).matches()) .max(Comparator.comparingInt(file -> { Matcher matcher = pattern.matcher(file.getName()); if (matcher.find()) { int year = Integer.parseInt(matcher.group(1)); int month = Integer.parseInt(matcher.group(2)); return year * 100 + month; } return 0; })) .orElse(null); } if (fileToConvert == null) { return ResponseEntity.notFound().build(); } // 以下为文件转换为PDF的代码 try (XWPFDocument document = new XWPFDocument(new FileInputStream(fileToConvert)); ByteArrayOutputStream out = new ByteArrayOutputStream()) { PdfOptions options = PdfOptions.create(); PdfConverter.getInstance().convert(document, out, options); byte[] pdfContent = out.toByteArray(); ByteArrayResource resource = new ByteArrayResource(pdfContent); return ResponseEntity.ok() .contentLength(pdfContent.length) .header("Content-type", "application/pdf") .body(resource); } } @GetMapping("/quarterLatest") public ResponseEntity<Resource> quarterLatest(@RequestParam(required = false) String name) throws IOException { File folder = new File(QUARTER_PATH); File[] files = folder.listFiles((dir, filename) -> filename.endsWith(".docx")); if (files == null || files.length == 0) { return ResponseEntity.notFound().build(); } File fileToConvert; if (name != null && !name.isEmpty()) { // 用户选择了特定的文件 fileToConvert = Arrays.stream(files) .filter(file -> file.getName().equals(name)) .findFirst() .orElse(null); } else { // 没有特定选择,找最新的文件 Pattern pattern = Pattern.compile("(\\d{4})年(?:\\d{2})月-(\\d{4})年(?:\\d{2})月风光资源趋势预测\\.docx|" + "(\\d{4})年(?:\\d{2})-(\\d{2})月风光资源趋势预测\\.docx"); fileToConvert = Arrays.stream(files) .filter(file -> pattern.matcher(file.getName()).matches()) .max(Comparator.comparingInt(file -> { Matcher matcher = pattern.matcher(file.getName()); if (matcher.find()) { if (matcher.group(1) != null) { // 处理跨年文件名 int yearStart = Integer.parseInt(matcher.group(1)); int yearEnd = Integer.parseInt(matcher.group(2)); return yearEnd * 100 + (matcher.group(4) != null ? Integer.parseInt(matcher.group(4)) : 0); } else if (matcher.group(3) != null) { // 处理同一年文件名 int year = Integer.parseInt(matcher.group(3)); int monthEnd = Integer.parseInt(matcher.group(4)); return year * 100 + monthEnd; } } return 0; })) .orElse(null); } if (fileToConvert == null) { return ResponseEntity.notFound().build(); } // 文件转换为PDF的代码 try (XWPFDocument document = new XWPFDocument(new FileInputStream(fileToConvert)); ByteArrayOutputStream out = new ByteArrayOutputStream()) { PdfOptions options = PdfOptions.create(); PdfConverter.getInstance().convert(document, out, options); byte[] pdfContent = out.toByteArray(); ByteArrayResource resource = new ByteArrayResource(pdfContent); return ResponseEntity.ok() .contentLength(pdfContent.length) .header("Content-type", "application/pdf") .body(resource); } } @GetMapping("/monthList") public List<String> listAllDocs() { File folder = new File(MONTH_PATH); // 修改为获取.docx文件 File[] files = folder.listFiles((dir, name) -> name.endsWith(".docx")); if (files == null) { return Collections.emptyList(); } // 返回文件名列表 return Arrays.stream(files) .map(File::getName) .collect(Collectors.toList()); } @GetMapping("/quarterList") public List<String> quarterList() { File folder = new File(QUARTER_PATH); // 修改为获取.docx文件 File[] files = folder.listFiles((dir, name) -> name.endsWith(".docx")); if (files == null) { return Collections.emptyList(); } // 返回文件名列表 return Arrays.stream(files) .map(File::getName) .collect(Collectors.toList()); } }
前端代码html代码,使用两个按钮,点击后弹出模态框,在模态框中有iframe来展示pdf:
<!-- 模态框(Modal) --> <div class="modal fade" id="pdfModalMonth" tabindex="-1" role="dialog" aria-labelledby="pdfModalLabelMonth" aria-hidden="true"> <div class="modal-dialog" style="max-width: 90%; width: auto;"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title" id="pdfModalLabelMonth">月度预测文档</h4> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <!-- 下拉框用于选择文档 --> <select id="MonthList" class="form-control"> <option value="">请选择文档</option> <!-- 文档列表将在这里填充 --> </select> <iframe id="MonthViewer" style="width:100%; height:700px;"></iframe> <!-- 可以根据需要调整高度 --> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> </div> </div> </div> </div> <div class="modal fade" id="pdfModalQuarter" tabindex="-1" role="dialog" aria-labelledby="pdfModalLabelQuarter" aria-hidden="true"> <div class="modal-dialog" style="max-width: 90%; width: auto;"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title" id="pdfModalLabelQuarter">月度预测文档</h4> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <!-- 下拉框用于选择文档 --> <select id="QuarterList" class="form-control"> <option value="">请选择文档</option> <!-- 文档列表将在这里填充 --> </select> <iframe id="QuarterViewer" style="width:100%; height:700px;"></iframe> <!-- 可以根据需要调整高度 --> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> </div> </div> </div> </div> <a class="btn btn-sm btn-primary" id="loadMonth" style="text-decoration: none;color: #ffffff">月度预测</a> <a class="btn btn-sm btn-primary" id="loadQuarter" style="text-decoration: none;color: #ffffff">季度预测</a>
js代码:
$(document).ready(function() { // 加载月度列表 function loadMonthList() { $.get("/api/document/monthList", function(data) { // 清空现有的选项 $("#MonthList").empty(); $("#MonthList").append('<option value="">请选择文档</option>'); // 假设文档名包含日期,例如 "2024年01月风光资源趋势预测.docx" // 对文档进行倒序排序 data.sort(function(a, b) { // 转换为日期格式进行比较 var dateA = new Date(a.split('年')[0], a.split('年')[1].split('月')[0] - 1); var dateB = new Date(b.split('年')[0], b.split('年')[1].split('月')[0] - 1); return dateB - dateA; // 从新到旧排序 }); // 添加新的选项 data.forEach(function(doc) { $("#MonthList").append('<option value="' + doc + '">' + doc + '</option>'); }); }); } // 当点击加载最新文档的按钮时 $("#loadMonth").click(function() { loadMonthList(); // 调用函数加载文档列表 // 加载最新的PDF文档 $("#MonthViewer").attr("src", "/api/document/monthLatest"); // 显示模态框 $("#pdfModalMonth").modal("show"); }); // 当选择不同的文档时 $("#MonthList").change(function() { var selectedFile = $(this).val(); if(selectedFile) { $("#MonthViewer").attr("src", "/api/document/monthLatest?name=" + encodeURIComponent(selectedFile)); } }); // 加载季度列表 function parseDateFromDocName(docName) { var year, month; var parts = docName.match(/(\d{4})年(\d{2})-(\d{2})月|(\d{4})年(\d{2})月-(\d{4})年(\d{2})月/); if (parts) { if (parts[1]) { // 格式是 "YYYY年MM-DD月" year = parseInt(parts[1], 10); month = parseInt(parts[2], 10); // 使用开始月份 } else { // 格式是 "YYYY年MM月-YYYY年MM月" year = parseInt(parts[4], 10); month = parseInt(parts[5], 10); // 使用开始月份 } } return new Date(year, month - 1); // JavaScript中的月份是从0开始的 } function loadQuarterList() { $.get("/api/document/quarterList", function(data) { // 清空现有的选项 $("#QuarterList").empty(); $("#QuarterList").append('<option value="">请选择文档</option>'); // 对文档进行倒序排序 data.sort(function(a, b) { var dateA = parseDateFromDocName(a); var dateB = parseDateFromDocName(b); return dateB - dateA; // 从新到旧排序 }); // 添加新的选项 data.forEach(function(doc) { $("#QuarterList").append('<option value="' + doc + '">' + doc + '</option>'); }); }); } // 当点击加载最新文档的按钮时 $("#loadQuarter").click(function() { loadQuarterList(); // 调用函数加载文档列表 // 加载最新的PDF文档 $("#QuarterViewer").attr("src", "/api/document/quarterLatest"); // 显示模态框 $("#pdfModalQuarter").modal("show"); }); // 当选择不同的文档时 $("#QuarterList").change(function() { var selectedFile = $(this).val(); if(selectedFile) { $("#QuarterViewer").attr("src", "/api/document/quarterLatest?name=" + encodeURIComponent(selectedFile)); } }); });
做完一切后,发现有些文档中的标题的中文没有显示出来,我就对比显示的文档和没显示的文档,发现是因为字体的原因,宋体是可以显示出来的,但是宋体(中文)显示不出来。把宋体(中文)改成宋体就可以显示。
但是这只是我windows系统上运行是没问题的,我把项目部署到服务器(centos)后,发现中文一点都展示不出来,这时候我就很纳闷,为什么在windows上能显示出来,linux上显示不出来,经过查阅资料,我发现是由于Linux上缺乏一些中文字体,例如宋体、仿宋等,这些字体是我文档中用到的字体,所以下一步我要将windows中的字体放在服务器上。
在Linux系统中安装宋体(SimSun)字体,需要手动下载字体文件或从Windows系统中复制字体文件,然后将其安装到Linux系统中。宋体不包含在开源字体包中,因为它是微软的商业字体。下面是一般步骤:
sudo mkdir -p /usr/share/fonts/chinese
sudo cp ~/Downloads/simsun.ttc /usr/share/fonts/chinese/
sudo fc-cache -fv
fc-list | grep "simsun"
至此,大功告成!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。