1生成pdf并通过输出流返回生成的pdf文件(常用于下载pdf)
2生成pdf并上传到minio,并返回图片的url(常用于pdf的预览)
场景梳理
1 ,根据事先制作好的pdf模板生成pdf(使用Adobe Acrobat软件)
2, 在用户签名处给pdf加上签名的图片
3, 给pdf生成水印(水印可换行)
4, 直接返回输出流给前端,前端直接可以下载pdf
需要的pom依赖 <!-- 导出pdf需要使用的包:xdocreport --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>org.apache.poi.xwpf.converter.core</artifactId> <version>1.0.4</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>org.apache.poi.xwpf.converter.pdf</artifactId> <version>1.0.4</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.itext.extension</artifactId> <version>1.0.4</version> </dependency> <!-- 文件流转化需要的依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.20</version> </dependency>
该方法的代码如下
package com.ruoyi.common.utils; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import com.itextpdf.text.pdf.AcroFields.Item; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUtils; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; /** * pdf工具类 * * @author wuhuc * @data 2022/7/12 - 9:12 */ public class PdfUtill { /** * @param templatePdfPath 模板pdf路径 * @param data 数据 */ public static void generatePDFByOutputStream(String templatePdfPath, Map<String, Object> data, Map<String, byte[]> imgMap, HttpServletResponse response) { OutputStream fos = null; ByteArrayOutputStream bos = null; try { PdfReader reader = new PdfReader(templatePdfPath); bos = new ByteArrayOutputStream(); /* 将要生成的目标PDF文件名称 */ PdfStamper ps = new PdfStamper(reader, bos); PdfGState gs = new PdfGState(); gs.setFillOpacity(0.4f);// 设置透明度 /* 使用中文字体 */ BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); ArrayList<BaseFont> fontList = new ArrayList<BaseFont>(); fontList.add(bf); int total = reader.getNumberOfPages() + 1; PdfContentByte content; for (int i = 1; i < total; i++) { content = ps.getOverContent(i); content.beginText(); content.setGState(gs); content.setColorFill(BaseColor.DARK_GRAY); //水印颜色 content.setFontAndSize(bf, 20); //水印字体样式和大小 final String username = SecurityUtils.getUsername(); for (int x = 0; x < 700; x = x + 300) { for (int y = 0; y < 900; y = y + 200) { //水印内容和水印位置 content.showTextAligned(Element.ALIGN_CENTER, "xxx", x - 20, y + 10, 30); content.showTextAligned(Element.ALIGN_CENTER, username + LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN), x, y, 30); } } content.endText(); } /* 取出报表模板中的所有字段 */ AcroFields fields = ps.getAcroFields(); fields.setSubstitutionFonts(fontList); fillData(fields, data); // 添加图片 if (imgMap != null) { addImage(ps, fields, imgMap); } /* 必须要调用这个,否则文档不会生成的 如果为false那么生成的PDF文件还能编辑,一定要设为true*/ ps.setFormFlattening(true); ps.close(); //设置导出的数据的文件流 response.setContentType("application/pdf"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("xxx", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf"); fos = response.getOutputStream(); fos.write(bos.toByteArray()); fos.flush(); } catch (Exception e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static AjaxResult generatePDFByMinio(String templatePdfPath, Map<String, Object> data, Map<String, byte[]> imgMap) { ByteArrayOutputStream bos = null; try { PdfReader reader = new PdfReader(templatePdfPath); bos = new ByteArrayOutputStream(); /* 将要生成的目标PDF文件名称 */ PdfStamper ps = new PdfStamper(reader, bos); PdfGState gs = new PdfGState(); gs.setFillOpacity(0.4f);// 设置透明度 /* 使用中文字体 */ BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); ArrayList<BaseFont> fontList = new ArrayList<BaseFont>(); fontList.add(bf); int total = reader.getNumberOfPages() + 1; PdfContentByte content; for (int i = 1; i < total; i++) { content = ps.getOverContent(i); content.beginText(); content.setGState(gs); //水印颜色 content.setColorFill(BaseColor.DARK_GRAY); //水印字体样式和大小 content.setFontAndSize(bf, 20); final String username = SecurityUtils.getUsername(); for (int x = 0; x < 700; x = x + 300) { for (int y = 0; y < 900; y = y + 200) { //水印内容和水印位置 content.showTextAligned(Element.ALIGN_CENTER, "xxx", x - 20, y + 10, 30); content.showTextAligned(Element.ALIGN_CENTER, username + LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN), x, y, 30); } } content.endText(); } /* 取出报表模板中的所有字段 */ AcroFields fields = ps.getAcroFields(); fields.setSubstitutionFonts(fontList); fillData(fields, data); // 添加图片 if (imgMap != null) { addImage(ps, fields, imgMap); } /* 必须要调用这个,否则文档不会生成的 如果为false那么生成的PDF文件还能编辑,一定要设为true*/ ps.setFormFlattening(true); ps.close(); final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray()); MultipartFile file = new MockMultipartFile("xxx.pdf", "xxx.pdf", "application/pdf", byteArrayInputStream); String fileName = FileUploadUtils.uploadMinio(file); AjaxResult ajax = AjaxResult.success(); ajax.put("url", fileName); ajax.put("fileName", fileName); ajax.put("newFileName", FileUtils.getName(fileName)); ajax.put("originalFilename", file.getOriginalFilename()); return ajax; } catch (Exception e) { e.printStackTrace(); return AjaxResult.error(e.getMessage()); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } private static void fillData(AcroFields fields, Map<String, Object> data) throws IOException, DocumentException, DocumentException { List<String> keys = new ArrayList<String>(); Map<String, Item> formFields = fields.getFields(); for (String key : data.keySet()) { if (formFields.containsKey(key)) { //忽略值为null的字段 if (data.get(key) != null) { String value = String.valueOf(data.get(key)); fields.setField(key, value, true); // 为字段赋值,注意字段名称是区分大小写的 keys.add(key); } } } Iterator<String> itemsKey = formFields.keySet().iterator(); while (itemsKey.hasNext()) { String itemKey = itemsKey.next(); if (!keys.contains(itemKey)) { fields.setField(itemKey, " "); } } } private static void addImage(com.itextpdf.text.pdf.PdfStamper ps, com.itextpdf.text.pdf.AcroFields fields, Map<String, byte[]> imgMap) throws IOException, com.itextpdf.text.DocumentException { for (String key : imgMap.keySet()) { int pageNo = fields.getFieldPositions(key).get(0).page; Rectangle signRect = fields.getFieldPositions(key).get(0).position; float x = signRect.getLeft(); float y = signRect.getBottom(); // 读图片 Image image = Image.getInstance(imgMap.get(key)); // 获取操作的页面 PdfContentByte under = ps.getOverContent(pageNo); // 根据域的大小缩放图片 image.scaleToFit(signRect.getWidth(), signRect.getHeight()); // 添加图片 image.setAbsolutePosition(x, y); under.addImage(image); } } }