1、使用Adobe Acrobat创建PDF模板(设置文本域),文本域命名对应Java实体类
2、引入依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
3、编写实现类和控制类
@Service
@Slf4j
public class PdfServiceImpl implements PdfService {
@Override
public void generator(Invoice invoice, HttpServletResponse response) throws UnsupportedEncodingException, FileNotFoundException {
// 模板名称
String templateName = "Invoice_elle_April2022模板.pdf";
String path = "";
// 获取操作系统名称,根据系统名称确定模板存放的路径
String systemName = System.getProperty("os.name");
if (systemName.toUpperCase().startsWith("WIN")) {
path = "C:/Users/Administrator/Desktop/";
}
// 生成导出PDF的文件名称
String fileName = "Invoice.pdf";
fileName = URLEncoder.encode(fileName, "UTF-8");
// 设置响应头
response.setCharacterEncoding("UTF-8");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
OutputStream out = null;
PdfReader reader = null;
ByteArrayOutputStream bos;
PdfStamper stamper;
try {
// 保存到本地
// out = new FileOutputStream(fileName);
// 输出到浏览器端
out = response.getOutputStream();
// 读取PDF模板表单
reader = new PdfReader(path + templateName);
// 字节数组流,用来缓存文件流
bos = new ByteArrayOutputStream();
// 根据模板表单生成一个新的PDF
stamper = new PdfStamper(reader, bos);
// 获取新生成的PDF表单
AcroFields form = stamper.getAcroFields();
// 给表单生成中文字体,这里采用系统字体,不设置的话,中文显示会有问题
BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
form.addSubstitutionFont(font);
// 装配数据
Map<String, Object> data = new HashMap<>(15);
data.put("billedTo", invoice.getBilledTo());
data.put("dateOfIssue", invoice.getDateOfIssue());
data.put("invoiceNumber", invoice.getInvoiceNumber());
data.put("amountDue", invoice.getAmountDue());
data.put("description", invoice.getDescription());
data.put("rate", invoice.getRate());
data.put("qty", invoice.getQty());
data.put("lineTotal", invoice.getLineTotal());
data.put("total", invoice.getTotal());
// 遍历data,给pdf表单赋值
for (String key : data.keySet()) {
form.setField(key, data.get(key).toString());
}
// 表明该PDF不可修改
stamper.setFormFlattening(true);
// 关闭资源
stamper.close();
// 将ByteArray字节数组中的流输出到out中(即输出到浏览器)
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
log.info("*****************************PDF导出成功*********************************");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.flush();
out.close();
}
if (reader != null) {
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public interface PdfService {
void generator(Invoice invoice, HttpServletResponse response) throws UnsupportedEncodingException, FileNotFoundException;
}
@RestController
@RequestMapping("/pdf")
public class PdfController {
@Autowired
private PdfService pdfService;
@PostMapping("/export")
public void generatorAdmissionCard(@RequestBody Invoice invoice, HttpServletResponse response) {
try {
pdfService.generator(invoice, response);
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
}
}
}
4、导出效果(字体和换行可在Adobe Acrobat中设置)
5、字体找不到问题(windows本地可以,线上环境报错)
问题代码
BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
解决办法
1.引入依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
2.上面代码改成
BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
参考文章:
Java如何实现Pdf的导出?