Java Applet中的Apache FOP - 没有为数据找到ImagePreloader

时间:2014-10-01 10:29:20

标签: java applet apache-fop

我正在研究成熟商业产品中的问题。

简而言之,我们使用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库的安全问题,但无济于事。

有什么想法吗?

谢谢,

3 个答案:

答案 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?在解决此问题时对我很有帮助。