问题描述
我有一个用 Flying Saucer 生成的工作 PDF。然而,当我现在想要添加自定义字体时,生成的 PDF 会损坏。浏览器没有下载文件,而是显示了各种奇怪的符号。
自定义字体是通过在类路径上添加 ttf 字体文件并调用 addFont
来添加的:
renderer.getFontResolver().addFont("/fonts/Montserrat-Regular.ttf",BaseFont.IDENTITY_H,true);
renderer.getFontResolver().addFont("/fonts/Montserrat-Italic.ttf",true);
renderer.getFontResolver().addFont("/fonts/Montserrat-Bold.ttf",true);
renderer.getFontResolver().addFont("/fonts/Montserrat-BoldItalic.ttf",true);
并在 CSS 中指定字体:
html {
font-family: 'Montserrat',sans-serif;
font-size: 14px;
}
解决方法
问题是由于在将 PDF 生成到响应的输出流中之后设置了响应标头。
我的控制器是这样的:
@GetMapping("/{id}/download-pdf")
@Secured(Roles.ADMIN)
public void downloadPDFResource(@PathVariable("id") EntityId entityId,HttpServletRequest request,HttpServletResponse response,Locale locale) throws IOException {
byte[] pdf = pdfService.generatePdf("details-pdf",context);
response.getOutputStream().write(pdf);
response.setContentType("application/pdf");
response.addHeader("Content-Disposition","attachment; filename=" + "document.pdf");
response.getOutputStream().flush();
}
修复方法是将内容类型和标题的设置移动到方法的顶部:
@GetMapping("/{id}/download-pdf")
@Secured(Roles.ADMIN)
public void downloadPDFResource(@PathVariable("id") EntityId entityId,Locale locale) throws IOException {
response.setContentType("application/pdf");
response.addHeader("Content-Disposition","attachment; filename=" + "document.pdf");
byte[] pdf = pdfService.generatePdf("details-pdf",context);
response.getOutputStream().write(pdf);
response.getOutputStream().flush();
}