Java生成PDF几种方式

发布时间 2023-04-09 11:59:46作者: bigcat11

## 1、itextPDF直接填充
<!-- PDF工具类 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- PDF中文支持 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13.1</version>
</dependency>


```java
**Impl实现类**
// 设置response参数,可以打开下载页面
response.reset();
response.setCharacterEncoding("UTF-8");
// 定义输出类型
response.setContentType("application/PDF;charset=utf-8");
// 设置名称
String filename;
try {
filename=new String("生成PDF".getBytes("gb2312"), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
response.setHeader("Content-Disposition", "attachment; filename=" + filename+".pdf");
try (OutputStream out = response.getOutputStream()) {
// 生成pdf
createPdfPage(out);

} catch (IOException e) {
throw new RuntimeException(e);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
public void createPdfPage(OutputStream out) throws DocumentException {

// 创建文档
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, out);
document.open();
// 报告标题
document.add(PdfFontUtil.getParagraph("****单", TITLE_FONT, 1));
// 生成6列的表格
PdfPTable dataTable = PdfFontUtil.getPdfTable(4, 500);
// 设置表格
dataTable.addCell(PdfFontUtil.getParagraph("xxxx", CONTENT_FONT, Element.ALIGN_CENTER));

dataTable.addCell(PdfFontUtil.getParagraph(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ", Locale.CHINESE).format(new Date()), CONTENT_FONT, Element.ALIGN_CENTER));

document.add(dataTable);
document.newPage();
//关闭流
document.close();
writer.close();

public class PdfFontUtil {

private PdfFontUtil() {
}

/**
* 基础配置,可以放相对路径,这里演示绝对路径,因为字体文件过大,这里不传到项目里面了,需要的自己下载
* 下载地址:https://www.zitijia.com/downloadpage?itemid=281258939050380345
*/
public static final String FONT = "src/main/resources/static/SimHei.ttf";

/**
* 基础样式
*/
public static final Font TITLE_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, 20, Font.BOLD);
public static final Font NODE_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, 15, Font.BOLD);
public static final Font BLOCK_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, 13, Font.BOLD, BaseColor.BLACK);
public static final Font INFO_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, 12, Font.NORMAL, BaseColor.BLACK);
public static final Font CONTENT_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);


/**
* 段落样式获取
*/
public static Paragraph getParagraph(String content, Font font, Integer alignment) {
Paragraph paragraph = new Paragraph(content, font);
if (alignment != null && alignment >= 0) {
paragraph.setAlignment(alignment);
}
return paragraph;
}

/**
* 图片样式
*/
public static Image getImage(String imgPath, float width, float height) throws IOException, BadElementException {
Image image = Image.getInstance(imgPath);
image.setAlignment(Image.MIDDLE);
if (width > 0 && height > 0) {
image.scaleAbsolute(width, height);
}
return image;
}

/**
* 表格生成
*/
public static PdfPTable getPdfTable(int numColumns, float totalWidth) {
// 表格处理
PdfPTable table = new PdfPTable(numColumns);
// 设置表格宽度比例为%100
table.setWidthPercentage(100);
// 设置宽度:宽度平均
table.setTotalWidth(totalWidth);
// 锁住宽度
table.setLockedWidth(true);
// 设置表格上面空白宽度
table.setSpacingBefore(10f);
// 设置表格下面空白宽度
table.setSpacingAfter(10f);
// 设置表格默认为无边框
// table.getDefaultCell().setBorder(0);
table.setPaddingTop(50);
table.setSplitLate(false);
return table;
}

/**
* 表格内容带样式
*/
public static void addTableCell(PdfPTable dataTable, Font font, List<String> cellList) {
for (String content : cellList) {
dataTable.addCell(getParagraph(content, font, -1));
}
}
```

## 2、使用itextpdf包直接原生写样式
1. 使用word制作需要的模板生成pdf
2. 使用Adobe编辑添加文本域
3. 使用模板填充
> 此方法在填充时,出现字体异常、内容消失等问题,不适合内容动态填充
## 3、使用word模板填充在转PDF
> 推荐好用方便
1、使用poi-tl包完成
<!-- 方法二转pdf-->
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>15.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
打包aspose时需要注意把包 下载放到项目根录下创建一个lib包下

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- 打包时会将本地jar一起打包 -->
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>


<!-- 转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>

**poi包,此处版本冲突一下版本经过测试无冲突**
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
<version>2.0.2</version>
</dependency>


<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.9.1</version>
</dependency>

1. 制作word模板,需要填充的内容填写{{var}}等参考poi-tl官方文档
2. 填充后转pdf
```java
String filePath = templatePath+"word.docx";

XWPFTemplate template = XWPFTemplate.compile(filePath);

Map map=new HashMap<String, Object>() {};
map.put("var", “测试”);

FileOutputStream outputStream1 = new FileOutputStream(wordTempPath);
template.writeAndClose(outputStream1);
//转pdf方法 使用documents4j 直接转pdf
// 方法1:
// File inputWord = new File("D:\\Desktop\\11.docx");
// File outputFile = new File("D:\\Desktop\\11.pdf");
// InputStream docxInputStream = new FileInputStream(inputWord);
// OutputStream outputStream = new FileOutputStream(outputFile);
// IConverter converter = LocalConverter.builder().build();
// converter.convert(docxInputStream).as(DocumentType.DOC).to(outputStream).as(DocumentType.PDF).execute();
// outputStream.close();
使用aspose 方法导出
// 方法2:
AsposeUtil.getLicense();//获取许可证去水印
File file = new File("D:\\Desktop\\11.pdf");
try (FileOutputStream os = new FileOutputStream(file)) {
Document doc = new Document(wordTempPath);
doc.save(os, SaveFormat.PDF);
}
//判断word是否存在?存在删除 word 只保留pdf
File wordFile = new File(wordTempPath);
if (wordFile.exists()){
wordFile.delete();
}


```

```java
AsposeUtil 工具类
public class AsposeUtil {
/**
* 加载license 用于破解 不生成水印
*/
@SneakyThrows
public static void getLicense() {
try (InputStream is = AsposeUtil.class.getClassLoader().getResourceAsStream("License.xml")) {
License license = new License();
license.setLicense(is);
}
}

/**
* word转pdf
*
* @param wordPath word文件保存的路径
* @param pdfPath 转换后pdf文件保存的路径
*/
@SneakyThrows
public static void wordToPdf(String wordPath, String pdfPath) {
getLicense();
File file = new File(pdfPath);
try (FileOutputStream os = new FileOutputStream(file)) {
Document doc = new Document(wordPath);
doc.save(os, SaveFormat.PDF);
}
}
}

```
xml文件 ,放到resourse目录下
```java
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>
sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
</Signature>
</License>


```