将大量ODT文件可靠快速地转换为PDF的办法?

6 投票
5 回答
2782 浏览
提问于 2025-04-15 23:07

我需要从一个简单的模板(几页和表格)预先生成一百万到两百万个PDF文件,里面还要嵌入字体。通常在这种情况下,我会使用像ReportLab这样的库来低层次地处理所有内容,但我这个项目是后来加入的。

现在,我有一个template.odt文件,并在content.xml文件中使用标记来填充数据库中的数据。我可以顺利地创建ODT文件,它们看起来总是正确的。

为了将ODT转换为PDF,我在服务器模式下使用openoffice(还用到了PyODConverter和命名管道),但这并不太可靠:在一批文档中,最终会有一个时刻,之后所有处理的文件都变成了垃圾(字体错误,字母乱七八糟地分布在页面上)。

这个问题并不是每次都能预测到(与数据无关),在OOo 2.3和3.2版本中都会出现,操作系统包括Ubuntu、XP、Server 2003和Windows 7。我的Heisenbug探测器正在响。

我尝试减少批处理的大小,并在每次处理后重启OOo;不过,仍然有一小部分文档出现了问题。

当然,我会在Ooo的邮件列表上写这个问题,但与此同时,我有交付的任务,已经浪费了太多时间。

我该怎么办呢?

  1. 完全避免使用ODT格式,换成其他模板系统。

    • 有什么建议吗?任何运行几秒钟的程序都太慢了。OOo大约需要一秒钟,这加起来就要15天的处理时间。我不得不写一个程序来将任务分配到多个客户端。
  2. 保留这个格式,但换个工具或程序来进行转换。

    • 哪个工具好呢?在Windows的共享软件或商业软件库中有很多应用,但逐个尝试实在是个艰巨的任务。有些太慢,有些在批处理时需要先购买,有些不能从命令行运行,等等。
    • 开源工具往往不想重新发明轮子,通常也依赖于openoffice。
  3. 转换成中间的.DOC格式可能有助于避免OOo的bug,但这会使处理时间翻倍,并且让已经很复杂的任务变得更麻烦。

  4. 尝试生成PDF两次并进行比较,如果有问题就丢掉整批。

    • 虽然文档看起来一样,但我不知道有什么方法可以比较二进制内容。
  5. 在处理每个文档后重启OOo。

    • 这会花费更多时间来生成文件。
    • 这会降低错误文件的比例,但也会让识别它们变得非常困难。
  6. 使用ReportLab程序化地重新创建页面。这是我接下来要尝试的方法。

  7. 学习如何正确格式化项目符号列表。

非常感谢。

补充:看来我根本无法使用ReportLab,它不让我嵌入字体。我的字体有TrueType和OpenType版本。

TrueType版本显示“TTFError: 字体不允许子集/嵌入(0100)”。

OpenType版本显示“TTFError[...] 不支持PostScript轮廓”。

真是太有趣了。

5 个回答

0

这个问题很有意思。既然你已经把它写成可以在多台机器上运行的程序,为什么不试试双重生产的方法,把它分布到EC2节点上呢?这样可能会多花一点钱,但你可以用md5或sha这样的哈希值来比较不同的版本,如果两个版本是一样的,那你就可以继续进行下一步了。

3

如果你要生成大量的PDF文件,OpenOffice可能不是个好选择。你应该使用专门为生成大量PDF文件而优化的报告工具。市面上有很多不同的工具。我推荐i-net Clear Reports(以前叫i-net Crystal-Clear)。

  • 我觉得用这个工具生成一个PDF文件会比用OpenOffice快。
  • 如果你要生成两个PDF文件并进行比较,会浪费很多时间。
  • 它可以嵌入True Type字体。
  • 通过API,你可以在一个循环中进行操作。
  • 使用试用许可证,你可以在90天内进行批量处理。

不过缺点是你需要重新开始你的开发工作。

2

我可能会找到一种方法来判断批处理什么时候出问题,然后从出问题前不久的地方重新处理所有内容。怎么判断出问题了呢?这需要分析一些正常的PDF文件和一些失败的文件,看看它们之间有什么相似之处:

  • 生成的文件大小和源文件不匹配
  • 文件里缺少某些字符串(比如你的字体名称)
  • 某些数据不在预期的位置
  • 转换回文本时,里面没有模板中应该有的数据
  • 转换成位图时,文本的位置不对

我觉得把它们转换回文本并寻找预期的字符串可能是最准确的解决方案,但也会比较慢。如果对每个文件都这么慢,那就可以每100个文件中选一个来处理,然后在最后一个已知正常的文件之后,重新转换所有文件。

撰写回答