Adobe Reader 无法从我的项目中读取字体?
Adobe Reader cannot read fonts from my project?
我正在使用 iTextPdf version 5
生成 PDF,并在该 PDF 中使用 Calibri font
。我在使用 Boot 时从 src/resource/fonts
文件夹加载了该字体。一切正常,因为我可以在我的项目中查看该 PDF 并下载,除了当我尝试使用 Adobe Reader 打开 PDF 时,页面显示类似的内容 -
我已经使用 Google Chrome、WPS office 和其他 PDF Reader 打开了那个 PDF,那个 PDF 工作得很好,但我似乎无法理解哪里出了问题当我尝试使用 Adobe 查看 PDF 时。下面我也附上了WPS office中PDF的截图-
这是我在 PDF 中加载字体的代码 -
static URL calibriFont = UserProfileController.class.getResource("/static/fonts/Calibri Regular.ttf");
static Font namefont = FontFactory.getFont(calibriFont.toString(), 20, Font.BOLD, new BaseColor(139, 0, 0));
FontFactory.register(calibriFont.toString());
这是下面分享的 PDF 文件 link -
Sample PDF
简而言之
初始生成后向 PDF 添加了额外数据,引入了交叉引用错误。取文件的前1019493字节得到原始工作文件
我的第一个猜测是另一个程序错误地对 PDF 进行了后处理,但结果是 iText 对象被错误地关闭导致了那个错误。
详细
您共享的 PDF 的最终版本不是由 iText 生成的,至少不是由 iText 的正确使用生成的。
文件大小为 1021972 字节。最初的 1019493 字节构成了一个有效的 PDF。
额外的 2479 字节扩展了 PDF,提供了一些更新的旧对象、一些新对象和完整的交叉引用 table。而在这个交叉引用table中第一个新对象33的偏移条目是不正确的,它应该是0001019493(原始内容后添加的第一个字节,即第一个新对象的开始)但它是0001018667(原始 PDF 的交叉引用 table 的开始)。
因此,PDF 处理器在查找新对象 33 时将错误地找到原始交叉引用。
由于对象 33 恰好包含更新对象 1 中字体 Calibri 的 FontDescriptor,因此尝试解析此字体失败。所有文档页面都引用了该字体。
因此,Adobe Reader 在遇到使用该字体的指令时立即停止绘制每一页。
其他一些 PDF 查看器会在后台修复该错误,因此会显示您想要查看的内容。
实际原因
在您写的评论中
The error was coming due to PdfWriter instance object was closed before document.
确实,您根本不需要关闭 PdfWriter
,尤其是在 Document
之前。
当使用 PdfWriter.getInstance
为 Document
请求 PdfWriter
时,会创建一个 PdfDocument
实例并将其注册为 Document
的侦听器;然后创建 PdfWriter
并注册为 PdfDocument
.
的侦听器
要完成 PDF 生成,您需要关闭 Document
。这将调用它的监听器各自的 close
方法,即 PdfDocument.close
,它将完成一些最后的对象,写入它们,然后调用它自己的监听器的 close
方法,即 PdfWriter.close
,这将写入交叉引用。
在您的代码中,您首先显式调用了 PdfWriter.close
(它编写了第一个交叉引用 table),然后是 Document.close
(这导致 PdfDocument
编写了一些对象和然后再次触发 PdfWriter.close
以编写第二个交叉引用)。这个不正确的序列也导致了不正确的交叉引用偏移。
我已经找到了我的问题的解决方案,我已经关闭了文档之前的 PdfWriter
个实例。当我在文档后关闭那个实例时,它工作正常。
我正在使用 iTextPdf version 5
生成 PDF,并在该 PDF 中使用 Calibri font
。我在使用 Boot 时从 src/resource/fonts
文件夹加载了该字体。一切正常,因为我可以在我的项目中查看该 PDF 并下载,除了当我尝试使用 Adobe Reader 打开 PDF 时,页面显示类似的内容 -
我已经使用 Google Chrome、WPS office 和其他 PDF Reader 打开了那个 PDF,那个 PDF 工作得很好,但我似乎无法理解哪里出了问题当我尝试使用 Adobe 查看 PDF 时。下面我也附上了WPS office中PDF的截图-
这是我在 PDF 中加载字体的代码 -
static URL calibriFont = UserProfileController.class.getResource("/static/fonts/Calibri Regular.ttf");
static Font namefont = FontFactory.getFont(calibriFont.toString(), 20, Font.BOLD, new BaseColor(139, 0, 0));
FontFactory.register(calibriFont.toString());
这是下面分享的 PDF 文件 link - Sample PDF
简而言之
初始生成后向 PDF 添加了额外数据,引入了交叉引用错误。取文件的前1019493字节得到原始工作文件
我的第一个猜测是另一个程序错误地对 PDF 进行了后处理,但结果是 iText 对象被错误地关闭导致了那个错误。
详细
您共享的 PDF 的最终版本不是由 iText 生成的,至少不是由 iText 的正确使用生成的。
文件大小为 1021972 字节。最初的 1019493 字节构成了一个有效的 PDF。
额外的 2479 字节扩展了 PDF,提供了一些更新的旧对象、一些新对象和完整的交叉引用 table。而在这个交叉引用table中第一个新对象33的偏移条目是不正确的,它应该是0001019493(原始内容后添加的第一个字节,即第一个新对象的开始)但它是0001018667(原始 PDF 的交叉引用 table 的开始)。
因此,PDF 处理器在查找新对象 33 时将错误地找到原始交叉引用。
由于对象 33 恰好包含更新对象 1 中字体 Calibri 的 FontDescriptor,因此尝试解析此字体失败。所有文档页面都引用了该字体。
因此,Adobe Reader 在遇到使用该字体的指令时立即停止绘制每一页。
其他一些 PDF 查看器会在后台修复该错误,因此会显示您想要查看的内容。
实际原因
在您写的评论中
The error was coming due to PdfWriter instance object was closed before document.
确实,您根本不需要关闭 PdfWriter
,尤其是在 Document
之前。
当使用 PdfWriter.getInstance
为 Document
请求 PdfWriter
时,会创建一个 PdfDocument
实例并将其注册为 Document
的侦听器;然后创建 PdfWriter
并注册为 PdfDocument
.
要完成 PDF 生成,您需要关闭 Document
。这将调用它的监听器各自的 close
方法,即 PdfDocument.close
,它将完成一些最后的对象,写入它们,然后调用它自己的监听器的 close
方法,即 PdfWriter.close
,这将写入交叉引用。
在您的代码中,您首先显式调用了 PdfWriter.close
(它编写了第一个交叉引用 table),然后是 Document.close
(这导致 PdfDocument
编写了一些对象和然后再次触发 PdfWriter.close
以编写第二个交叉引用)。这个不正确的序列也导致了不正确的交叉引用偏移。
我已经找到了我的问题的解决方案,我已经关闭了文档之前的 PdfWriter
个实例。当我在文档后关闭那个实例时,它工作正常。