.NET 中的 FOP 和 IKVM - 图像无法正常工作
更新2:我现在完全可以使用了!向下滚动以了解如何...
更新:我成功了!嗯...部分。向下滚动寻找答案...
我试图让我的 FO 文件在将其转换为 PDF(或 RTF)后显示外部图像,但我不确定 RTF 是否是甚至能够使用 FOP 显示图像 (它们是)),但我似乎无法让它工作。 (这里提出的问题与我的不同。)
我正在使用 IKVM 0.46.0.1并编译了一个 FOP 1.0 dll 以放入 .NET 中;当我没有尝试添加图像时,此代码工作正常:
private void convertFoByMimetype(java.io.File fo, java.io.File outfile, string mimetype)
{
OutputStream output = null;
try
{
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
// configure foUserAgent as desired
// Setup outputput stream. Note: Using BufferedOutputStream
// for performance reasons (helpful with FileOutputStreams).
output = new FileOutputStream(outfile);
output = new BufferedOutputStream(output);
// Construct fop with desired output format
Fop fop = fopFactory.newFop(mimetype, foUserAgent, output);
// Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer
// Setup input stream
Source src = new StreamSource(fo);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
}
catch (Exception ex)
...
}
但是,当我(或者更确切地说是 DocBook2FO 转换)添加以下代码时:
<fo:external-graphic src="url(images/interface.png)" width="auto" height="auto" content-width="auto" content-height="auto" content-type="content-type:image/png"></fo:external-graphic>
到 FO 文件中,图像没有显示。我通读了一些 Apache 网站上的常见问题解答,其中说:
3.3。为什么我的图形没有渲染?
最常见的是,FOP 找不到外部文件。检查 以下:
baseDir 设置为空或错误。
文件名中的拼写错误(包括使用错误的大小写)。
...
其他选项似乎不适合我的情况(主要是由于以下原因 - “奇怪的部分”)。我尝试过这个:
...
try
{
fopFactory.setBaseURL(fo.getParent());
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
foUserAgent.setBaseURL(fo.getParent());
FOURIResolver fourir = fopFactory.getFOURIResolver();
foUserAgent.setURIResolver(fourir);
// configure foUserAgent as desired
...
没有效果。
奇怪的部分
当我使用 FOP 的命令行实现时,它工作正常并且显示我的图像没有任何问题。 (我不想走程序中运行命令行的路线,因为我不想强迫用户在想要使用我的程序时安装 Java 和 .NET 框架。)
png 文件是从我的应用程序中的 GDI+ 生成的(使用 Bitmap.Save)。我也尝试了不同的 png 文件,但它们都不适合我。
我可能缺少什么吗?
非常感谢您提供到目前为止的
更新和可能的答案
所以我可能已经弄清楚为什么它不起作用了。我花了一些时间研究代码(之前我基本上只是复制粘贴它而没有考虑太多)。问题确实出在错误的 basedir 设置上。
关键在于这段代码:
// Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer
// Setup input stream
Source src = new StreamSource(fo);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
这里发生的是身份转换,它将自己的结果路由到我之前创建的 FOP 实例中。这有效地将路由 FO 的 basedir 更改为应用程序可执行文件的 basedir。我还没有弄清楚如何在不进行转换的情况下做到这一点,并将我的输入直接路由到 FOP 中,但目前我通过将图像复制到可执行文件的目录中来解决这个问题。
这就是另一个问题出现的地方。现在,每当我尝试执行代码时,我都会在 transformer.transform(src, res);
行出现异常,这让我很困惑,因为它什么也没说。异常助手说:
java.lang.ExceptionInInitializerError 被捕获
,并且没有内部异常或异常消息。我知道仅根据我所写的内容很难进行调试,但我希望可能有一个简单的解决方案。
UPDATE2
最后,经过几个不眠之夜,我设法用最简单的方法之一让它工作。
我更新了 IKVM,用新版本编译了 fop,并用新的 dll 替换了 IKVM 引用。错误不再发生,我的图像呈现良好。
我希望有一天这可以帮助别人
UPDATE2: I got it working completely now! Scroll way down to find out how...
UPDATE: I got it working! Well... partially. Scroll down for the answer...
I'm trying to get my FO file to show an external image upon transforming it to PDF (or RTF for that matter, but I'm not sure whether RTFs are even capable of displaying images (they are)) with FOP, but I can't seem to get it working. (The question asked here is different than mine.)
I am using IKVM 0.46.0.1 and have compiled a FOP 1.0 dll to put in .NET; this code worked fine when I didn't try to add images:
private void convertFoByMimetype(java.io.File fo, java.io.File outfile, string mimetype)
{
OutputStream output = null;
try
{
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
// configure foUserAgent as desired
// Setup outputput stream. Note: Using BufferedOutputStream
// for performance reasons (helpful with FileOutputStreams).
output = new FileOutputStream(outfile);
output = new BufferedOutputStream(output);
// Construct fop with desired output format
Fop fop = fopFactory.newFop(mimetype, foUserAgent, output);
// Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer
// Setup input stream
Source src = new StreamSource(fo);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
}
catch (Exception ex)
...
}
However, when I (or rather a DocBook2FO transformation) added the following code:
<fo:external-graphic src="url(images/interface.png)" width="auto" height="auto" content-width="auto" content-height="auto" content-type="content-type:image/png"></fo:external-graphic>
into the FO file, the image did not show. I read through a bit of the FAQ on Apache's site, which says:
3.3. Why is my graphic not rendered?
Most commonly, the external file is not being found by FOP. Check the
following:Empty or wrong baseDir setting.
Spelling errors in the file name (including using the wrong case).
...
Other options did not seem to be my case (mainly for the reason below - "The Weird Part"). I tried this:
...
try
{
fopFactory.setBaseURL(fo.getParent());
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
foUserAgent.setBaseURL(fo.getParent());
FOURIResolver fourir = fopFactory.getFOURIResolver();
foUserAgent.setURIResolver(fourir);
// configure foUserAgent as desired
...
with no avail.
The Weird Part
When I use the command-line implementation of FOP, it works fine and displays my image with no problem. (I don't want to go the run-command-line-from-program route, because I don't want to force the users to install Java AND the .NET framework when they want to use my program.)
The png file is generated from GDI+ from within my application (using Bitmap.Save). I also tried different png files, but none of them worked for me.
Is there anything I might be missing?
Thanks a bunch for getting this far
UPDATE and possible answer
So I might have figured out why it didn't work. I put some time into studying the code (before I basically just copypasted it without thinking about it much). The problem is indeed in the wrong basedir setting.
The key is in this chunk of code:
// Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer
// Setup input stream
Source src = new StreamSource(fo);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
What happens here is an identity transformation, which routes its own result into an instance of FOP I've created before. This effectively changes the basedir of the routed FO into that of the application's executable. I have yet to figure out how to do this without a transformation and route my input directly into FOP, but for the moment I worked around this by copying my images into the executable's directory.
Which is where another problem came in. Now whenever I try to execute the code, I get an exception at the line that says transformer.transform(src, res);
, which confuses the pants out of me, because it doesn't say anything. The ExceptionHelper says:
java.lang.ExceptionInInitializerError was caught
and there is no inner exception or exception message. I know this is hard to debug just from what I wrote, but I'm hoping there might be an easy fix.
Also, this e-mail seems vaguely related but there is no answer to it.
UPDATE2
Finally, after a few sleepless nights, I managed to get it working with one of the simplest ways possible.
I updated IKVM, compiled fop with the new version and replaced the IKVM references with the new dlls. The error no longer occurs and my image renders fine.
I hope this helps someone someday
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我正在使用非常相似的代码,尽管没有 FOUserAgent、Resolvers 等,但它工作得很好。
您是否尝试在不使用
url()
函数的情况下在 XSLT 中设置src
属性?以下语句可能会帮助您进一步诊断问题:
其中
TraceStream
是java.io.OutputStream
的 .NET 实现,它写入您最喜欢的记录器。我在 http://pastebin.com/XH1Wg7jnCommon.Logging 包的版本一个>。
I'm using very similar code, although without the FOUserAgent, Resolvers, etc. and it works perfectly.
Did you try setting the
src
attribute in the XSLT without theurl()
function?What might help you diagnose the problem further are the following statements:
Where
TraceStream
is a .NET implementation of ajava.io.OutputStream
which writes to your favorite logger.I posted a version for the
Common.Logging
package at http://pastebin.com/XH1Wg7jn.这是一个不要让问题悬而未决的帖子,请参阅原始帖子中的“更新 1”和“更新 2”以获取解决方案。
Here's a post not to leave the question unanswered, see "Update 1" and "Update 2" in the original post for the solution.