Java Applet 中的 Apache FOP - 未找到用于数据的 ImagePreloader [英] Apache FOP in a Java Applet - No ImagePreloader found for data

查看:20
本文介绍了Java Applet 中的 Apache FOP - 未找到用于数据的 ImagePreloader的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究成熟商业产品中的一个问题.

I'm looking at an issue in a mature commercial product.

简而言之,我们使用 Apache POI 库的一部分来读取 Word .DOC 或 .DOCX 文件,并将其转换为 XSL-FO,以便我们可以进行标记替换.然后我们使用 FOP(嵌入到 Java 程序中)将 FO 数据转换为 PDF 进行打印.问题是,所有这些都是在 Internet Explorer 中运行的 Java 小程序中的客户端上完成的.

In a nutshell, we are using part of the Apache POI library to read in a Word .DOC or .DOCX file, and convert it into XSL-FO so that we can do token replacements. We then use FOP – embedded into the Java program - to convert the FO data into a PDF for printing. The catch is, all this is being done on the client inside a Java applet running inside Internet Explorer.

最初我们使用 FOP 0.93,它运行得相当好.但是,它在生成 PDF 时无法利用 DOC 文件中的字体,并且会将所有内容映射到 Times,这是一位客户不喜欢的.从理论上讲,它可以通过添加某种字体度量数据来工作,但这需要对可能遇到的每种字体进行相对复杂的定义,而且我们无法预测客户端可能会在 MS 之外使用什么核心字体集.

Originally we were using FOP 0.93, which worked reasonably well. However, it was not able to utilise the fonts inside the DOC file when generating the PDF and would map everything to Times, which one of the customers did not like. In theory it could be made to work by adding some kind of font metrics data, but that would require a relatively complex definition for every font it was likely to encounter and we can’t predict what the client is liable to use outside of the MS core fonts set.

为了解决这个问题,FOP 升级到 1.0,增加了对从操作系统自动检测字体的支持.这有效,但我们注意到图像处理停止工作,信头也消失了.似乎发生的事情是 FOP 中的图像加载器在 0.93 和 0.95 之间的某个时间点被重写,因此现在使用 ImageIO 而不是使用 Jimi 和 JAI.较早的实现工作正常,但新代码不喜欢作为小程序运行.

To fix this, FOP was upgraded to 1.0, which added support for autodetecting the fonts from the operating system. This worked, but we noticed that the image processing had stopped working and the letterheads had disappeared. What appears to have happened is that the image loader inside FOP was rewritten at some point between 0.93 and 0.95 so that instead of using Jimi and JAI it now uses ImageIO. The earlier implementation worked fine, but the new code doesn’t like being run as an applet.

图像嵌入在 FO 数据的 URI 中,因此我们收到如下错误:2014-09-30 17:00:10,607 错误 [org.apache.fop.apps.FOUserAgent] 图像不可用.网址:数据:图像/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAA...……嘎嘎==.原因:org.apache.xmlgraphics.image.loader.ImageException:不支持文件格式.未找到数据的 ImagePreloader:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAAA...

Images are embedded in URIs in the FO data so we get an error like this: 2014-09-30 17:00:10,607 ERROR [org.apache.fop.apps.FOUserAgent] Image not available. URI: data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAA... ...ggg==. Reason: org.apache.xmlgraphics.image.loader.ImageException: The file format is not supported. No ImagePreloader found for data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAAA...

当通过测试工具运行时,会生成正确的输出,但是当在浏览器中作为小程序运行时,我们得到上述错误,这让我怀疑浏览器小程序安全以某种方式干扰了 ImageIO 插件加载器.

When run through a test harness, the correct output is generated, but when run as an applet inside the browser we get the above error which makes me suspect that the browser applet security is jamming the ImageIO plugin loader somehow.

FOP 转换的核心,即触发错误的位是这样的:

The guts of the FOP transformation, i.e. the bit which is triggering the error is this:

// 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 访问权限来管理字体缓存.

...which is all being run inside a PrivilegedAction block since in FOP 1.0 it needed file I/O access to manage the font cache.

在 linux 下运行独立的 FOP 0.93 和 1.0 程序并使用 strace 表明它正在为图像数据写出临时文件,但是 0.93 和 1.0 都做类似的事情,所以它本身不应该是这样,特别是因为它应该已经拥有创建临时文件的权限.

Running the standalone FOP 0.93 and 1.0 programs under linux and using strace shows that it is writing out temporary files for the image data, but both 0.93 and 1.0 do similar things, so it shouldn’t be that by itself, especially since it should have permission to create temp files already.

我尝试了不同版本的 JRE,因为几年前的一些构建显然存在 ImageIO 库的安全问题,但无济于事.

I've tried different versions of the JRE since some builds a few years back apparently had security issues with the ImageIO library, but to no avail.

有什么想法吗?

谢谢,

推荐答案

如果其他人有类似的情况,结果证明这是由项目在 Maven 中构建的方式造成的.

In case anyone else has something similar, this turned out to be caused by the way the project was being built in Maven.

Fop 1.0 及以上版本使用 xml-graphics-commons 库来方便图像渲染.正如问题中提到的,这使用了一个插件注册表,该注册表是使用 JAR 中的以下文件配置的:

Fop 1.0 and above use the xml-graphics-commons library to facilitate the image rendering. As mentioned in the question, this uses a plugin registry which is configured using the following files inside the JAR:

META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter
META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader

META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter
META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader

...每个都包含将支持的图像解码器列表.

...each of these contains a list of the image decoders which will be supported.

问题是 xml-graphics-common 将这些文件与合理的默认值列表一起发送,而 FOP 也有一组相互冲突的默认值,出于某种奇怪的原因禁用了所有图像解码器,而那个优先.

The problem is that xml-graphics-common ships these files with a sensible list of defaults, while FOP also has a conflicting set of defaults, which for some weird reason disable all of the image decoders, and that one was taking priority.

为了解决这个问题,我确保我的 maven pom.xml 文件在 FOP 之前导入了 xml-graphics-common ,因此它的默认值优先,在这一点上一切都变得生动起来.

To solve the problem, I made sure that my maven pom.xml file imported xml-graphics-common before FOP, so that its defaults took precedence, and at that point everything sprang to life.

我仍然不确定为什么代码作为独立测试程序可以正常工作,但我怀疑这是处理类路径的方式与在插件模式下运行的方式不同.

I am still not sure why the code was working correctly as a standalone test program, but I suspect it was the way the classpath was being handled being different to it running in plugin mode.

这篇关于Java Applet 中的 Apache FOP - 未找到用于数据的 ImagePreloader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆