使用OpenOffice无头方式将Docx转换为PDF太慢
我一直在使用PHPWord来生成docx文件,效果很好。
但现在我需要把这些文件也转成pdf格式。
经过一番研究,我发现了PyODConverter,它使用了OOo(OpenOffice)。这个选项看起来不错,因为我不想依赖第三方的网络服务。我在自己的电脑上试了一下,运行得很好,所以我也把它应用到了我的服务器上。虽然花了点时间,但我也成功让它在服务器上运行了。
不过,有一个(糟糕的)问题。在服务器上,这个过程大约需要21秒,而在我的电脑上最多只要2秒。:(这对我来说时间太长了,所以我一直在寻找可能导致这个延迟的原因。
在无头模式下启动OpenOffice并创建socket是没问题的。
所以我开始查看这个python脚本,想找出哪个指令可能导致了慢速。我把问题缩小到了这一行:
context = resolver.resolve("uno:socket,host=127.0.0.1,port=8100;urp;StarOffice.ComponentContext")
这个操作大约需要20秒才能执行。
它插入的代码如下:
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
try:
context = resolver.resolve("uno:socket,host=127.0.0.1,port=8100;urp;StarOffice.ComponentContext")
except NoConnectException:
raise DocumentConversionException, "failed to connect to OpenOffice.org on port %s" % port
self.desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
有没有什么线索可以帮助我找出导致这个延迟的原因?
我已经排除了我尝试转换的文档,因为这个操作发生在那之前。
可能是'uno'的问题吗?或者是缺少其他库,导致在resolve()操作时进行不必要的测试?
欢迎任何想法。:)
最好的祝福,Restless
3 个回答
也许服务器上的名字解析器不知道 localhost
是什么(这听起来很奇怪,但20秒的延迟确实像是DNS超时)。你可以试着把它换成 127.0.0.1
。
另外,可能它在查找时没问题,能同时获取到 localhost
的IPv6和IPv4地址,但在尝试通过IPv6连接时失败了(也就是说,可能这个组件不支持IPv6,或者默认不绑定到那个接口),然后才退回去用IPv4。在这种情况下,解决办法也是一样:把 localhost
换成 127.0.0.1
。
真可惜,OpenOffice 太占空间了。我之前也考虑过用它,但后来发现了一个更轻便的选择,就是 AbiWord。
我需要从上传的文档中生成前四页的预览。这是我做的:
abiword document.doc --to=ps --exp-props="pages:1-4"
gs -q -dNOPAUSE -dBATCH -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r72 -sDEVICE=pnggray -sOutputFile=preview%d.png document.ps
所以你可以去下载最新的 AbiWord,然后试试这样的做法:
abiword document.docx --to=pdf
我通过使用管道而不是套接字来消除延迟。
context = resolver.resolve("uno:pipe,name=myuser_OOffice;urp;StarOffice.ComponentContext")
不过我还有一个问题……执行这个Python脚本的用户必须和启动OOo的用户是同一个,才能让一切正常工作。通常这不是个大问题,但我现在想从我的网页应用程序中执行Python,结果还是没能搞定。
我尝试了类似这样的方式:
exec('sudo -u#1000 -s python path/to/DocumentConverter.py filename.docx filename.pdf');
但是我什么也没得到……我不明白为什么。可能是运行exec()的用户(www-data)没有权限执行sudo吧??