一、项目中加入了 iText 库。可以通过 Maven 引入 iText 依赖:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.4</version>
<type>pom</type>
</dependency>
二、创建PDF的依赖和方法
import java.util.*;
import java.util.List;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.layout.*;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.HorizontalAlignment;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public static ByteArrayOutputStream generatePDF() throws IOException {
// 创建一个字节输出流
ByteArrayOutputStream pdfStream = new ByteArrayOutputStream();
// 创建 PDF Writer 对象,绑定到 ByteArrayOutputStream
PdfWriter writer = new PdfWriter(pdfStream);
// 创建 PDF 文档
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
// 加载中文字体文件(确保你的项目中有这个文件)
// 字体文件路径根据你的实际情况进行修改
PdfFont font = PdfFontFactory.createFont("C:\\Windows\\Fonts\\simsun.ttc,0", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
// 添加标题(使用中文字体)
document.add(new Paragraph("部门信息与数据表格").setBold().setFontSize(16).setFont(font));
// 第一部分:部门的 Key-Value 信息展示
document.add(new Paragraph("\n部门信息:").setBold().setFont(font));
// 假设两个部门的 Key-Value 信息
Map<String, String> departmentData = new LinkedHashMap<>();
departmentData.put("部门名称", "技术部");
departmentData.put("部门负责人", "张经理");
departmentData.put("员工数量", "20人");
departmentData.put("部门位置", "大楼 3 层");
// 以 Key: Value 形式展示每一条数据
StringBuilder departmentInfo = new StringBuilder();
for (Map.Entry<String, String> entry : departmentData.entrySet()) {
departmentInfo.append(entry.getKey()).append(":").append(entry.getValue()).append(" ");
}
// 以一行显示所有 Key-Value 信息
document.add(new Paragraph(departmentInfo.toString().trim()).setFont(font));
// 第二部分:数据表格展示
document.add(new Paragraph("\n员工数据表:").setBold().setFont(font));
// 模拟一些员工数据
List<String[]> employeeData = new ArrayList<>();
employeeData.add(new String[] {"张三", "开发工程师", "8000"});
employeeData.add(new String[] {"李四", "测试工程师", "7000"});
employeeData.add(new String[] {"王五", "产品经理", "9000"});
// 创建表格并填充数据
Table dataTable = new Table(3); // 3 列,分别是 姓名、职位、工资
//设置表格宽度
dataTable.setWidth(400);
//设置表格居中
dataTable.setHorizontalAlignment(HorizontalAlignment.CENTER);
dataTable.addHeaderCell("姓名").setFont(font);
dataTable.addHeaderCell("职位").setFont(font);
dataTable.addHeaderCell("工资").setFont(font);
for (String[] row : employeeData) {
dataTable.addCell(row[0]).setFont(font);
dataTable.addCell(row[1]).setFont(font);
dataTable.addCell(row[2]).setFont(font);
}
document.add(dataTable);
// 关闭文档
document.close();
// 返回 PDF 文件的字节流
return pdfStream;
}
三、生成PDF文件或返给前端下载
//生成PDF文件
public static void main(String[] args) {
try {
// 生成 PDF 文件流
ByteArrayOutputStream pdfStream = generatePDF();
//创建文件
FileOutputStream fos = new FileOutputStream("D://output.pdf");
pdfStream.writeTo(fos);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//返给前端下载
@GetMapping("/download")
public ResponseEntity<byte[]> downloadPDF() throws IOException {
// 生成 PDF 文件的输出流
ByteArrayOutputStream pdfStream = generatePDF();
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData("attachment", "document.pdf"); // 设置下载文件名
headers.setContentLength(pdfStream.size());
// 返回 PDF 文件的字节数组
return ResponseEntity.ok()
.headers(headers)
.body(pdfStream.toByteArray());
}
四、结果展示
五、提示
如果有在Linux运行项目的需要,使用了一些比较新的字体,直接打包windows系统的字体可能会存在部分字体识别不出来。把windows系统字体上传到Linxu系统字体里可以得到解决。