From 7ca683ab04ec6f4abea56e4482f8feb34cc3acad Mon Sep 17 00:00:00 2001 From: weiweiw <14335254+weiweiw22@user.noreply.gitee.com> Date: Tue, 27 Aug 2024 14:10:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E8=AF=84=E5=AE=A1=E6=84=8F?= =?UTF-8?q?=E8=A7=81=E5=AE=8C=E5=96=84excel=EF=BC=8Cword=20=E5=92=8Cpdf?= =?UTF-8?q?=E7=9A=84=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bonus-common/bonus-common-core/pom.xml | 11 + .../bonus/common/core/utils/WordUtils.java | 309 ------------------ .../common/core/utils/file/FileUtils.java | 19 ++ .../common/core/utils/poi/DocumentUtil.java | 16 + .../bonus/common/core/utils/poi/PdfUtil.java | 113 +++++-- .../bonus/common/core/utils/poi/WordUtil.java | 32 +- .../common/core/utils/poi/PdfUtilTests.java | 75 ++++- .../common/core/utils/poi/WordUtilTests.java | 41 ++- .../system/controller/SysLogController.java | 5 +- 9 files changed, 266 insertions(+), 355 deletions(-) delete mode 100644 bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/WordUtils.java diff --git a/bonus-common/bonus-common-core/pom.xml b/bonus-common/bonus-common-core/pom.xml index 5aa6a30..6e61446 100644 --- a/bonus-common/bonus-common-core/pom.xml +++ b/bonus-common/bonus-common-core/pom.xml @@ -148,6 +148,17 @@ itextpdf 5.5.9 + + com.itextpdf + itext-asian + 5.2.0 + + + org.mockito + mockito-core + 1.10.19 + test + diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/WordUtils.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/WordUtils.java deleted file mode 100644 index 65df398..0000000 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/WordUtils.java +++ /dev/null @@ -1,309 +0,0 @@ -package com.bonus.common.core.utils; - -import freemarker.template.Configuration; -import freemarker.template.Template; -import org.apache.commons.io.IOUtils; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.net.URLEncoder; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Map; -import java.util.Objects; - -/** - * 实用程序类,用于生成和导出Word和PDF文档。 - * 还提供下载文件和读取文件内容的方法。 - */ -public class WordUtils { - - public static String pdf_fix = "pdf"; - public static String doc_fix = "doc"; - public static String docx_fix = "docx"; - - /** - * FreeMarker配置实例 - */ - private static Configuration configuration = null; - - static { - configuration = new Configuration(Configuration.VERSION_2_3_30); - configuration.setDefaultEncoding("utf-8"); - configuration.setClassForTemplateLoading(WordUtils.class, "/download/"); - } - - // 私有构造函数,防止实例化 - private WordUtils() { - throw new AssertionError(); - } - - /** - * 导出生成的Word文档 - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 - * @param map 数据模型 - * @param title 文件标题 - * @param ftlFile FreeMarker模板文件 - * @throws IOException 可能抛出的IO异常 - */ - public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException { - Template freemarkerTemplate = configuration.getTemplate(ftlFile); - File file = null; - InputStream fin = null; - ServletOutputStream out = null; - try { - // 调用工具类的createDoc方法生成Word文档 - file = createDoc(map, freemarkerTemplate); - fin = new FileInputStream(file); - - response.setCharacterEncoding("utf-8"); - response.setContentType("application/msword"); - // 设置浏览器以下载的方式处理该文件名 - String fileName = title + ".docx"; - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); - - out = response.getOutputStream(); - byte[] buffer = new byte[512]; - int bytesToRead; - // 通过循环将读入的Word文件的内容输出到浏览器中 - while ((bytesToRead = fin.read(buffer)) != -1) { - out.write(buffer, 0, bytesToRead); - } - } finally { - if (fin != null) { - fin.close(); - } - if (out != null) { - out.close(); - } - // 删除临时文件 - if (file != null) { - file.delete(); - } - } - } - - /** - * 生成Word文档 - * @param dataMap 数据模型 - * @param template FreeMarker模板 - * @return 生成的Word文档文件 - */ - private static File createDoc(Map dataMap, Template template) { - String name = "sellPlan.doc"; - File f = new File(name); - try (Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8")) { - // 使用FreeMarker生成文档 - template.process(dataMap, w); - } catch (Exception ex) { - ex.printStackTrace(); - throw new RuntimeException(ex); - } - return f; - } - - /** - * 导出生成的Word文档到指定路径 - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 - * @param map 数据模型 - * @param title 文件标题 - * @param ftlFile FreeMarker模板文件 - * @param path 文件保存路径 - * @throws IOException 可能抛出的IO异常 - */ - public static void exportMillCertificateWord2(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile, String path) throws IOException { - Template freemarkerTemplate = configuration.getTemplate(ftlFile); - File file = null; - InputStream fin = null; - OutputStream out = null; - String uploadPath = path + "word" + File.separator; - try { - file = createDoc(map, freemarkerTemplate); - fin = new FileInputStream(file); - - File file2 = new File(uploadPath); - if (!file2.exists()) { - file2.mkdirs(); - } - String fileName = uploadPath + File.separator + title + ".doc"; - out = new FileOutputStream(new File(fileName)); - byte[] buffer = new byte[512]; - int bytesToRead; - while ((bytesToRead = fin.read(buffer)) != -1) { - out.write(buffer, 0, bytesToRead); - } - } finally { - if (fin != null) { - fin.close(); - } - if (out != null) { - out.close(); - } - if (file != null) { - file.delete(); - } - } - } - - /** - * 导出PDF文档 - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 - * @param titleName 文件标题 - * @param fileName 文件路径 - * @throws IOException 可能抛出的IO异常 - */ - public static void exportPdf(HttpServletRequest request, HttpServletResponse response, String titleName, String fileName) throws IOException { - File file = new File(fileName); - try (InputStream fin = new FileInputStream(file); ServletOutputStream out = response.getOutputStream()) { - response.setCharacterEncoding("utf-8"); - response.setContentType("application/pdf"); - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(titleName, "UTF-8")); - byte[] buffer = new byte[512]; - int bytesToRead; - while ((bytesToRead = fin.read(buffer)) != -1) { - out.write(buffer, 0, bytesToRead); - } - } - } - - /** - * 导出文件 - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 - * @param fileName 文件名 - * @param decode 文件内容的字节数组 - * @throws IOException 可能抛出的IO异常 - */ - public static void exportFile(HttpServletRequest request, HttpServletResponse response, String fileName, byte[] decode) throws IOException { - try (InputStream fin = new ByteArrayInputStream(decode); ServletOutputStream out = response.getOutputStream()) { - response.setCharacterEncoding("utf-8"); - String subfix = fileName.substring(fileName.lastIndexOf(".") + 1); - if (Objects.equals(subfix, pdf_fix)) { - response.setContentType("application/pdf"); - } else if (Objects.equals(subfix, doc_fix) || Objects.equals(subfix, docx_fix)) { - response.setContentType("application/msword"); - } - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); - byte[] buffer = new byte[512]; - int bytesToRead; - while ((bytesToRead = fin.read(buffer)) != -1) { - out.write(buffer, 0, bytesToRead); - } - } - } - - /** - * 下载指定路径的文件 - * @param outputDir 要下载的文件的绝对路径 - * @param fileName 文件名 - * @param response HttpServletResponse对象 - * @throws IOException 可能抛出的IO异常 - */ - public static void fileDown(String outputDir, String fileName, HttpServletResponse response) throws IOException { - try (FileInputStream is = new FileInputStream(new File(outputDir))) { - response.setContentType("text/html;charset=utf-8"); - response.setCharacterEncoding("UTF-8"); - response.setHeader("content-disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\""); - ServletOutputStream os = response.getOutputStream(); - IOUtils.copy(is, os); - } - } - - /** - * 下载Word文件 - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 - * @param titleName 文件标题 - * @param fileName 文件路径 - * @throws IOException 可能抛出的IO异常 - */ - public static void exportWord(HttpServletRequest request, HttpServletResponse response, String titleName, String fileName) throws IOException { - File file = new File(fileName); - try (InputStream fin = new FileInputStream(file); ServletOutputStream out = response.getOutputStream()) { - response.setCharacterEncoding("utf-8"); - response.setContentType("application/msword"); - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(titleName, "UTF-8")); - byte[] buffer = new byte[512]; - int bytesToRead; - while ((bytesToRead = fin.read(buffer)) != -1) { - out.write(buffer, 0, bytesToRead); - } - } - } - - /** - * 下载视频文件 - * @param request HttpServletRequest对象 - * @param response HttpServletResponse对象 - * @param titleName 文件标题 - * @param fileName 文件路径 - * @throws IOException 可能抛出的IO异常 - */ - public static void exportVideo(HttpServletRequest request, HttpServletResponse response, String titleName, String fileName) throws IOException { - File file = new File(fileName); - try (InputStream fin = new FileInputStream(file); ServletOutputStream out = response.getOutputStream()) { - response.setCharacterEncoding("utf-8"); - response.setContentType("video/mp4"); - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(titleName, "UTF-8")); - byte[] buffer = new byte[512]; - int bytesToRead; - while ((bytesToRead = fin.read(buffer)) != -1) { - out.write(buffer, 0, bytesToRead); - } - file.delete(); - } - } - - /** - * 主方法,包含文件读取的示例 - * @param args 命令行参数 - * @throws IOException 可能抛出的IO异常 - */ - public static void main(String[] args) throws IOException { - String filePath = "F:\\File\\guest.txt"; - Path path = Paths.get(filePath); - - // 使用GBK编码读取文件 - try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "GBK"))) { - String line; - while ((line = reader.readLine()) != null) { - // 处理每一行的内容 - System.out.println(line); - } - } catch (IOException e) { - e.printStackTrace(); - } - - // 使用UTF-8编码读取文件 - try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"))) { - String line; - while ((line = reader.readLine()) != null) { - // 处理每一行的内容 - System.out.println(line); - } - } catch (IOException e) { - e.printStackTrace(); - } - - // 读取文件的字节内容并转换为字符串 - byte[] data = Files.readAllBytes(path); - String result = new String(data, "GBK-8"); - System.out.println(result); - - // 使用FileInputStream和InputStreamReader读取文件内容 - try (FileInputStream fis = new FileInputStream(filePath); - InputStreamReader isr = new InputStreamReader(fis); - BufferedReader br = new BufferedReader(isr)) { - String strTmp; - while ((strTmp = br.readLine()) != null) { - System.out.println(strTmp); - } - } - } -} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/file/FileUtils.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/file/FileUtils.java index 0dffad1..01cc598 100644 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/file/FileUtils.java +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/file/FileUtils.java @@ -13,9 +13,11 @@ import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import com.bonus.common.core.utils.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -277,4 +279,21 @@ public class FileUtils { return null; } } + + /** + * 下载指定路径的文件 + * @param outputDir 要下载的文件的绝对路径 + * @param fileName 文件名 + * @param response HttpServletResponse对象 + * @throws IOException 可能抛出的IO异常 + */ + public static void fileDownload(String outputDir, String fileName, HttpServletResponse response) throws IOException { + try (FileInputStream is = new FileInputStream(new File(outputDir))) { + response.setContentType("text/html;charset=utf-8"); + response.setCharacterEncoding("UTF-8"); + response.setHeader("content-disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\""); + ServletOutputStream os = response.getOutputStream(); + IOUtils.copy(is, os); + } + } } diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/DocumentUtil.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/DocumentUtil.java index b835d6f..3af721d 100644 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/DocumentUtil.java +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/DocumentUtil.java @@ -1,6 +1,7 @@ package com.bonus.common.core.utils.poi; import com.itextpdf.text.DocumentException; +import org.apache.commons.io.IOUtils; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; @@ -10,8 +11,13 @@ import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.general.DefaultPieDataset; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.net.URLEncoder; import java.text.DecimalFormat; public interface DocumentUtil { @@ -77,4 +83,14 @@ public interface DocumentUtil { return pieChart; } + public default void fileDown(String outputDir, String fileName, HttpServletResponse response) throws IOException { + try (FileInputStream is = new FileInputStream(new File(outputDir))) { + response.setContentType("text/html;charset=utf-8"); + response.setCharacterEncoding("UTF-8"); + response.setHeader("content-disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\""); + ServletOutputStream os = response.getOutputStream(); + IOUtils.copy(is, os); + } + } + } diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/PdfUtil.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/PdfUtil.java index 2ee8887..efc646b 100644 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/PdfUtil.java +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/PdfUtil.java @@ -1,6 +1,8 @@ package com.bonus.common.core.utils.poi; +import com.bonus.common.core.utils.StringUtils; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; +import lombok.Getter; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; @@ -9,41 +11,97 @@ import java.io.*; public class PdfUtil implements DocumentUtil { + /** + * -- GETTER -- + * 获取文档对象 + */ private final Document document; private final PdfWriter writer; + private BaseFont baseFont; + private int defaultFontSize = 12; /** * 初始化 PDF 文档 * @param pdfPath PDF 本地文件路径 + * @param fontPath 指定字体路径并将字体嵌入到pdf文档中保证在其他计算机上以同样字体显示,如果为空,则使用默认支持中文字体 + * @param defaultFontSize 指定字体大小,传入非整数值则默认为12 * @throws DocumentException 文档异常处理 * @throws IOException IO 异常处理 */ - public PdfUtil(String pdfPath) throws DocumentException, IOException { + public PdfUtil(String pdfPath, String fontPath, int defaultFontSize) throws DocumentException, IOException { + createBaseFont(fontPath); + if (defaultFontSize > 0) { + this.defaultFontSize = defaultFontSize; + } document = new Document(); writer = PdfWriter.getInstance(document, new FileOutputStream(pdfPath)); document.open(); } + /** + * 获取文档对象,以便对文档做其他自定义的操作 + */ + public Document getDocument() { + return document; + } + /** * 初始化 PDF 文档 * @param response http响应 + * @param fontPath 指定字体路径,如果为空,则使用默认支持中文字体 + * @param defaultFontSize 指定字体大小,默认为12 * @throws DocumentException 文档异常处理 * @throws IOException IO 异常处理 */ - public PdfUtil (HttpServletResponse response) throws DocumentException, IOException { + public PdfUtil (HttpServletResponse response, String fontPath, int defaultFontSize) throws DocumentException, IOException { + createBaseFont(fontPath); + if (defaultFontSize > 0) { + this.defaultFontSize = defaultFontSize; + } response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"generated.pdf\""); document = new Document(); writer = PdfWriter.getInstance(document, response.getOutputStream()); document.open(); } + + + public BaseFont getBaseFont() { + return baseFont; + } + + /* + * 设置PDF文档的元数据中的标题(通常通过“文件” -> “属性”)查看。 + * @param title 标题内容 + */ + public void addTitle(String title){ + document.addTitle(title); + } + + private void createBaseFont(String fontPath) throws DocumentException, IOException { + if (StringUtils.isNotBlank(fontPath)) { + File fontFile = new File(fontPath); + if (!fontFile.exists()) { + baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + } else { + baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED); + } + } + else { + baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + } + + } /** * 添加段落 * @param text 段落文本 - * @param font 字体样式 + * @param font 字体样式,为空则使用默认字体样式 * @throws DocumentException 文档异常处理 */ public Paragraph addParagraph(String text, Font font) throws DocumentException { + if (font == null) { + font = new Font(baseFont, defaultFontSize, Font.NORMAL); + } Paragraph paragraph = new Paragraph(text, font); document.add(paragraph); return paragraph; @@ -54,20 +112,23 @@ public class PdfUtil implements DocumentUtil { * @param headers 表头数组 * @param content 表格内容 * @param numCols 表格列数 + * @param font 字体样式,为空则使用默认字体样式 * @throws DocumentException 文档异常处理 */ - public void addTable(String[] headers, String[][] content, int numCols) throws DocumentException { + public void addTable(String[] headers, String[][] content, int numCols, Font font) throws DocumentException { + if (font == null) { + font = new Font(baseFont, defaultFontSize, Font.NORMAL); + } PdfPTable table = new PdfPTable(numCols); for (String header : headers) { - PdfPCell cell = new PdfPCell(new Phrase(header)); -// cell.setBackgroundColor(BaseColor.LIGHT_GRAY); + PdfPCell cell = new PdfPCell(new Phrase(header, font)); table.addCell(cell); } for (String[] row : content) { for (String cellData : row) { - table.addCell(cellData); + table.addCell(new Phrase(cellData, font)); } } @@ -79,10 +140,13 @@ public class PdfUtil implements DocumentUtil { * @param imagePath 图片文件路径 * @throws IOException IO 异常处理 * @throws DocumentException 文档异常处理 + * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素 + * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素 */ - public void addImage(String imagePath) throws IOException, DocumentException { + public void addImage(String imagePath, int width, int height) throws IOException, DocumentException { Image image = Image.getInstance(imagePath); - image.scaleToFit(500, 500); // 根据需求调整图片大小 + // 根据需求调整图片大小 + image.scaleToFit(width, height); document.add(image); } @@ -95,8 +159,10 @@ public class PdfUtil implements DocumentUtil { * @param fontSize 字体大小 * @throws DocumentException 文档异常处理 */ - public void addStyledParagraph(String text, boolean bold, boolean italic, int fontSize) throws DocumentException { - Font font = new Font(Font.FontFamily.TIMES_ROMAN, fontSize); + public void addStyledParagraph(String text, boolean bold, boolean italic, int fontSize, Font font) throws DocumentException { + if (font == null) { + font = new Font(baseFont, defaultFontSize, Font.NORMAL); + } if (bold) { font.setStyle(Font.BOLD); } @@ -112,11 +178,13 @@ public class PdfUtil implements DocumentUtil { * @param title 图表标题 * @param categories 目录轴的标签 * @param values 数据轴的标签 + * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素 + * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素 */ - public void addPieChart( String title, String[] categories, double[] values) throws IOException, DocumentException { + public void addPieChart( String title, String[] categories, double[] values, int width, int height) throws IOException, DocumentException { // 使用 JFreeChart 创建一个饼状图 JFreeChart pieChart = createPieChart(title, categories, values); - addChartToDocument(pieChart); + addChartToDocument(pieChart,width,height); } /** @@ -127,12 +195,14 @@ public class PdfUtil implements DocumentUtil { * @param rowKeys 目录轴每行的key * @param columnKeys 数据轴每列的key * @param data 数据 + * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素 + * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素 */ public void addBarChart(String title, String categoryAxisLabel, String valueAxisLabel, - String[] rowKeys, String[] columnKeys, double[][] data) throws IOException, DocumentException { + String[] rowKeys, String[] columnKeys, double[][] data, int width, int height) throws IOException, DocumentException { JFreeChart barChart = createBarChart(title, categoryAxisLabel, valueAxisLabel, rowKeys, columnKeys, data); - addChartToDocument(barChart); + addChartToDocument(barChart,width,height); } /** @@ -141,11 +211,15 @@ public class PdfUtil implements DocumentUtil { * @param chart JFreeChart 对象 * @throws IOException IO 异常处理 * @throws DocumentException 文档异常处理 + * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素 + * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素 */ - private void addChartToDocument(JFreeChart chart) throws IOException, DocumentException { - int width = 500; - int height = 400; - + private void addChartToDocument(JFreeChart chart, int width, int height) throws IOException, DocumentException { + width = (width > 0) ? width : 400; + height = (height > 0) ? height : 400; + if (chart == null) { + return; + } ByteArrayOutputStream chartOutput = new ByteArrayOutputStream(); ChartUtils.writeChartAsPNG(chartOutput, chart, width, height); Image chartImage = Image.getInstance(chartOutput.toByteArray()); @@ -153,7 +227,6 @@ public class PdfUtil implements DocumentUtil { document.add(chartImage); } - /** * 关闭文档 */ diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/WordUtil.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/WordUtil.java index 155ec12..05e7788 100644 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/WordUtil.java +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/poi/WordUtil.java @@ -2,7 +2,6 @@ package com.bonus.common.core.utils.poi; import com.itextpdf.text.DocumentException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.wp.usermodel.HeaderFooterType; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.util.Units; @@ -26,7 +25,7 @@ public class WordUtil implements DocumentUtil { } /** - * 获取文档对象 + * 获取文档对象,以便对文档做其他自定义的操作 */ public XWPFDocument getDocument() { return document; @@ -37,15 +36,15 @@ public class WordUtil implements DocumentUtil { * * @param text 文本内容 * @param fontSize 字体大小 - * @param font 默认字体为宋体 + * @param fontFamily 字体,如果指定字体不在当前系统,则使用默认字体 * @return XWPFParagraph 段落对象,可以用于更改段落其他属性 */ - public XWPFParagraph addParagraph(String text, int fontSize, String font) { + public XWPFParagraph addParagraph(String text, int fontSize, String fontFamily) { XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); run.setText(text); run.setFontSize(fontSize); - run.setFontFamily(font); + run.setFontFamily(fontFamily); return paragraph; } @@ -80,8 +79,8 @@ public class WordUtil implements DocumentUtil { * 创建图片,并插入到文档中 * * @param imgFilePath 图片本地路径 - * @param width 图片宽 - * @param height 图片高 + * @param width 图片宽,单位像素 + * @param height 图片高,单位像素 */ public void insertImage(String imgFilePath, int width, int height) throws RuntimeException { try (InputStream is = new FileInputStream(imgFilePath)) { @@ -102,19 +101,25 @@ public class WordUtil implements DocumentUtil { * @param rowKeys 目录轴每行的key * @param columnKeys 数据轴每列的key * @param data 数据 + * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素 + * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素 */ public void addBarChart(String title, String categoryAxisLabel, String valueAxisLabel, - String[] rowKeys, String[] columnKeys, double[][] data) throws IOException, DocumentException, InvalidFormatException { + String[] rowKeys, String[] columnKeys, double[][] data,int width,int height) throws IOException, DocumentException, InvalidFormatException { + + width = (width > 0) ? width : 400; + height = (height > 0) ? height : 400; + JFreeChart barChart = createBarChart(title, categoryAxisLabel, valueAxisLabel, rowKeys, columnKeys, data); ByteArrayOutputStream chartOut = new ByteArrayOutputStream(); - ChartUtils.writeChartAsPNG(chartOut, barChart, 400, 400); + ChartUtils.writeChartAsPNG(chartOut, barChart, width, height); // 将图表字节数组转为输入流并插入到文档中 ByteArrayInputStream chartIn = new ByteArrayInputStream(chartOut.toByteArray()); // Add chart to document XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); - run.addPicture(chartIn, XWPFDocument.PICTURE_TYPE_PNG, "bar_chart.png", Units.toEMU(400), Units.toEMU(400)); + run.addPicture(chartIn, XWPFDocument.PICTURE_TYPE_PNG, "bar_chart.png", Units.toEMU(width), Units.toEMU(height)); } /** @@ -124,12 +129,13 @@ public class WordUtil implements DocumentUtil { * @param categories 目录轴的标签 * @param values 数据轴的标签 */ - public void addPieChart( String title, String[] categories, double[] values) throws IOException, DocumentException, InvalidFormatException { + public void addPieChart( String title, String[] categories, double[] values,int width,int height) throws IOException, DocumentException, InvalidFormatException { JFreeChart pieChart = createPieChart(title, categories, values); - + width = (width > 0) ? width : 400; + height = (height > 0) ? height : 400; //将图表保存到字节数组输出流中 ByteArrayOutputStream chartOut = new ByteArrayOutputStream(); - ChartUtils.writeChartAsPNG(chartOut, pieChart, 400, 400); + ChartUtils.writeChartAsPNG(chartOut, pieChart, width, height); ByteArrayInputStream chartIn = new ByteArrayInputStream(chartOut.toByteArray()); //将图表字节数组转为输入流并插入到文档中 diff --git a/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/PdfUtilTests.java b/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/PdfUtilTests.java index f224e28..94027f9 100644 --- a/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/PdfUtilTests.java +++ b/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/PdfUtilTests.java @@ -1,24 +1,83 @@ package com.bonus.common.core.utils.poi; +import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; + +import com.itextpdf.text.Font; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.pdf.BaseFont; +import org.junit.Before; import org.junit.Test; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; +import org.mockito.Mockito; + +import static org.mockito.Mockito.when; public class PdfUtilTests { + private HttpServletResponse response; + private OutputStream outputStream; + @Before + public void setUp() throws IOException { + response = Mockito.mock(HttpServletResponse.class); + outputStream = new ByteArrayOutputStream(); + + // 使用匿名类模拟 ServletOutputStream + ServletOutputStream servletOutputStream = new ServletOutputStream() { + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + + @Override + public void write(int b) throws IOException { + outputStream.write(b); + } + }; + + when(response.getOutputStream()).thenReturn(servletOutputStream); + } @Test public void testPdf() throws IOException, DocumentException, InterruptedException { String currentPath = System.getProperty("user.dir"); - String fileName = currentPath+ "/src/test/java/com/bonus/common/core/utils/poi/testExport1.pdf"; - PdfUtil pdfUtil = new PdfUtil(fileName); - pdfUtil.addStyledParagraph("测试文字", true, false, 12); - pdfUtil.addTable(new String[] { "姓名", "年龄" }, new String[][] { { "张三", "18" }, { "李四", "19" } }, 2); - pdfUtil.addBarChart("柱状图", "月份", "数量", new String[] { "1", "2", "3" }, new String[] { "1", "2", "3" }, new double[][] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }); - pdfUtil.addPieChart("饼状图", new String[] { "1月份", "2月份", "3月份" }, new double[] { 1, 2, 3 }); + String fileName = currentPath+ "/src/test/java/com/bonus/common/core/utils/poi/testExport2.pdf"; + PdfUtil pdfUtil = new PdfUtil(fileName,null,0); + BaseFont baseFont = pdfUtil.getBaseFont(); + Document document = pdfUtil.getDocument(); + Font font = new Font(baseFont,24, Font.NORMAL); + Paragraph paragraph = new Paragraph("字体测试数据",font); + document.add(paragraph); + pdfUtil.addTitle("单元测试"); + pdfUtil.addStyledParagraph("测试文字", true, false, 12, font); + + pdfUtil.addTable(new String[] { "姓名", "年龄" }, new String[][] { { "张三", "18" }, { "李四", "19" } }, 2, null); + pdfUtil.addBarChart("柱状图", "月份", "数量", new String[] { "1", "2", "3" }, new String[] { "1", "2", "3" }, new double[][] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },400,400); + pdfUtil.addPieChart("饼状图", new String[] { "1月份", "2月份", "3月份" }, new double[] { 1, 2, 3 },400,400); pdfUtil.addParagraph("测试文字", null); - pdfUtil.addStyledParagraph("测试文字样式", true, true, 12); + pdfUtil.addStyledParagraph("测试文字样式", true, true, 12, null); String imagePath = currentPath + "/src/test/java/com/bonus/common/core/utils/poi/register.jpg"; - pdfUtil.addImage(imagePath); + pdfUtil.addImage(imagePath,400,400); pdfUtil.close(); } + + @Test + public void testPdfToResponse() throws IOException, DocumentException, InterruptedException { + String currentPath = System.getProperty("user.dir"); + PdfUtil pdfUtil = new PdfUtil(response,null,0); + pdfUtil.addTitle("单元测试"); + pdfUtil.addStyledParagraph("测试文字", true, false, 12, null); + pdfUtil.close(); + } + } diff --git a/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/WordUtilTests.java b/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/WordUtilTests.java index 67a4f5b..aa451f9 100644 --- a/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/WordUtilTests.java +++ b/bonus-common/bonus-common-core/src/test/java/com/bonus/common/core/utils/poi/WordUtilTests.java @@ -2,15 +2,51 @@ package com.bonus.common.core.utils.poi; import com.itextpdf.text.DocumentException; import org.apache.poi.wp.usermodel.HeaderFooterType; import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.OutputStream; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; public class WordUtilTests { + private HttpServletResponse response; + private OutputStream outputStream; + + @Before + public void setUp() throws IOException { + response = Mockito.mock(HttpServletResponse.class); + outputStream = new ByteArrayOutputStream(); + + // 使用匿名类模拟 ServletOutputStream + ServletOutputStream servletOutputStream = new ServletOutputStream() { + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + + @Override + public void write(int b) throws IOException { + outputStream.write(b); + } + }; + + when(response.getOutputStream()).thenReturn(servletOutputStream); + } @Test public void testWord() { @@ -21,9 +57,10 @@ public class WordUtilTests { wordUtil.addTable(2, 3, new String[][] { { "1", "2", "3" }, { "4", "5", "6" } }, new int []{3000,3000,3000}); XWPFDocument document = wordUtil.getDocument(); try { - wordUtil.addBarChart("柱状图", "", "数量", new String[]{"计划", "实际"}, new String[]{"第一季度", "第二季度", "第三季度"}, new double[][]{{1, 2,3}, {4, 5,6}}); - wordUtil.addPieChart("饼状图", new String[]{"1月份", "2月份", "3月份"}, new double[]{1, 2, 3}); + wordUtil.addBarChart("柱状图", "", "数量", new String[]{"计划", "实际"}, new String[]{"第一季度", "第二季度", "第三季度"}, new double[][]{{1, 2,3}, {4, 5,6}},0,0); + wordUtil.addPieChart("饼状图", new String[]{"1月份", "2月份", "3月份"}, new double[]{1, 2, 3},0,0); wordUtil.saveDocumentToLocal(fileName); + wordUtil.saveDocumentToResponse(response); wordUtil. closeDocument(); } catch (Exception ignored){ System.out.print("异常发生" + ignored.getMessage()); diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysLogController.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysLogController.java index a84f349..e6f81e0 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysLogController.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysLogController.java @@ -1,7 +1,7 @@ package com.bonus.system.controller; import com.bonus.common.core.domain.R; -import com.bonus.common.core.utils.WordUtils; +import com.bonus.common.core.utils.file.FileUtils; import com.bonus.common.core.web.controller.BaseController; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.web.page.TableDataInfo; @@ -9,7 +9,6 @@ import com.bonus.common.log.annotation.SysLog; import com.bonus.common.log.enums.OperaType; import com.bonus.common.core.utils.global.SystemGlobal; import com.bonus.system.api.domain.SysLogsVo; -//import com.bonus.system.service.ExportSqlService; import com.bonus.system.service.ExportSqlService; import com.bonus.system.service.ISysLogService; import io.swagger.annotations.ApiOperation; @@ -145,7 +144,7 @@ public class SysLogController extends BaseController { try { String dateTimeNow=exportSqlService.export("0"); String path=filePath + ExportSqlService.TABLE_NAME + dateTimeNow+ SystemGlobal.TEXT_FIX; - WordUtils.fileDown(path, "sys_log"+ dateTimeNow+".sql",response); + FileUtils.fileDownload(path, "sys_log"+ dateTimeNow+".sql",response); } catch (Exception e) { logger.error("文件下载失败", e); }