我正在研究成熟商业产品中的问题。
简而言之,我们使用Apache POI库的一部分来读取Word .DOC或.DOCX文件,并将其转换为XSL-FO,以便我们可以进行令牌替换。然后,我们使用FOP(嵌入到Java程序中)将FO数据转换为PDF以进行打印。问题是,所有这些都是在Internet Explorer中运行的Java applet内的客户端上完成的。
最初我们使用FOP 0.93,效果相当不错。但是,在生成PDF时无法利用DOC文件中的字体,并将所有内容映射到Times,其中一个客户不喜欢。理论上可以通过添加某种字体度量数据来使其工作,但这可能需要对它可能遇到的每种字体进行相对复杂的定义,并且我们无法预测客户端在MS之外可能使用的字体。核心字体集。
要解决此问题,FOP已升级到1.0,这增加了对从操作系统自动检测字体的支持。这很有效,但我们注意到图像处理已停止工作,信头已消失。 似乎发生的事情是FOP内的图像加载器在0.93和0.95之间的某个时刻被重写,因此它不使用Jimi和JAI,而是使用ImageIO。早期的实现工作正常,但新代码不喜欢作为applet运行。
图像嵌入在FO数据的URI中,因此我们得到如下错误: 2014-09-30 17:00:10,607 ERROR [org.apache.fop.apps.FOUserAgent]图片不可用。 URI: 数据:图像/ JPEG; BASE64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAA ... ... GGG ==。原因:org.apache.xmlgraphics.image.loader.ImageException:不支持文件格式。找不到数据的ImagePreloader:image / jpeg; base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAAA ...
当运行测试工具时,会生成正确的输出,但是当在浏览器中作为applet运行时,我们会收到上述错误,这让我怀疑浏览器applet安全性会以某种方式阻塞ImageIO插件加载程序。
FOP转换的内容,即触发错误的位是:
// Step 4: Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer
transformer.transform(src, res);
...这是在PrivilegedAction块中运行的,因为在FOP 1.0中它需要文件I / O访问来管理字体缓存。
在linux下运行独立的FOP 0.93和1.0程序并使用strace显示它正在写出图像数据的临时文件,但0.93和1.0都做类似的事情,所以它本身不应该是这样,特别是因为它应该有权创建临时文件。
我尝试过不同版本的JRE,因为几年前有些版本显然存在ImageIO库的安全问题,但无济于事。
有什么想法吗?
谢谢,
答案 0 :(得分:15)
如果其他人有类似的东西,结果是由于在Maven中构建项目的方式。
Fop 1.0及以上版本使用xml-graphics-commons库来促进图像渲染。正如问题中所提到的,这使用了一个插件注册表,它使用JAR中的以下文件进行配置:
META-INF /服务/ org.apache.xmlgraphics.image.loader.spi.ImageConverter
META-INF /服务/ org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
META-INF /服务/ org.apache.xmlgraphics.image.loader.spi.ImagePreloader
...每个都包含将支持的图像解码器列表。
问题是xml-graphics-common带有一个合理的默认列表,而FOP也有一组相互冲突的默认值,由于一些奇怪的原因,禁用了所有的图像解码器,而且一个优先考虑
为了解决这个问题,我确保我的maven pom.xml文件在 FOP之前导入了xml-graphics-common ,因此它的默认值优先,并且在那时一切都栩栩如生。
我仍然不确定为什么代码作为一个独立的测试程序正常工作,但我怀疑这是处理类路径与在插件模式下运行的方式不同的方式。
答案 1 :(得分:1)
刚刚在这个问题上苦苦挣扎。如果您使用maven-shade-plugin创建超级jar,请使用ServicesResourceTransformer
合并所有服务配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<!-- snip -->
<configuration>
<transformers>
<!-- snip -->
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
答案 2 :(得分:0)
在我的情况下,插件注册表从两个插件文件中加载了ImagePreloader
,并将它们混合在一起。但是错误仍然出现。我正在将SVG文件插入PDF文件。根本原因是org.apache.xmlgraphics:batik-svg-dom
的版本不正确。 1.7
需要org.apache.xmlgraphics:fop:1.1
版本,但是1.8
版本在类路径上。
两个版本之间有一个关键的区别:org.apache.fop.image.loader.batik.PreloaderSVG
类与类路径上的org.apache.batik.dom.svg.SAXSVGDocumentFactory
版本需要1.7
。如果它从org.apache.batik.anim.dom.SAXSVGDocumentFactory
版本获得1.8
,则无法正常工作。
这个SO问题:Where has org.apache.batik.dom.svg.SVGDOMImplementation gone?在解决此问题时对我很有帮助。