使用Flying Saucer解决受保护资源(ITextRenderer)

时间:2011-01-24 14:05:27

标签: java pdf resolve flying-saucer xhtmlrenderer

我正在使用Flying Saucer从xhtml创建一个pdf,托管在tomcat服务器上。 pdf中包含的大多数图像都是公开的(徽标等),但其中一些图像在登录后受到保护(即,如果用户登录,则通过servlet进行流式传输)。

当我在浏览器中粘贴网址时,图像当然显示正常,因为浏览器会发送带有请求的会话。但是当Flying Saucer呈现pdf时,它不包括受保护的图像,因为它对会话一无所知。

所以,我的问题是;是否有任何方法可以包含Flying Saucer的字节流来解决,就像可以添加可解析的字体一样?我尝试过像this这样的东西,但没有简单的方法在ITextRenderer上设置UAC,并且每次尝试都会抱怨。

2 个答案:

答案 0 :(得分:6)

您可以通过这种方式设置UserAgentCallback,Flying Saucer将使用它来解析网址(已测试,适用于第8版):

ITextRenderer renderer = new ITextRenderer();
renderer.getSharedContext().setUserAgentCallback(new MyUAC());

MyUAC应扩展NaiveUserAgent,并覆盖其他页面建议的resolveAndOpenStream方法。

答案 1 :(得分:2)

我也覆盖了ITextUserAgent - 从源代码看起来就像是ITextRenderer使用的东西。您必须在构造函数中提供输出设备,您可以从渲染器对象获取该输出设备。另一个问题是您必须使用setter方法显式设置“共享上下文” - 否则您将在渲染期间获得NPE。以下是设置对象的代码:

ITextRenderer renderer = new ITextRenderer();
MyUserAgentCallback uac = new MyUserAgentCallback(renderer.getOutputDevice());
uac.setSharedContext(renderer.getSharedContext());
renderer.getSharedContext().setUserAgentCallback(uac);

此外,以下是使用基本身份验证的MyUserAgentCallback的基本概念:

private static class MyUserAgentCallback extends ITextUserAgent
{
    public MyUserAgentCallback(ITextOutputDevice outputDevice)
    {
        super(outputDevice);
    }

    @Override
    protected InputStream resolveAndOpenStream(String uri) 
    {
        if (_isProtectedResource(uri))
        {
            java.io.InputStream is = null;
            uri = resolveURI(uri);
            try {
                URL url = new URL(uri);
                String encoding = new BASE64Encoder().encode ("username:password".getBytes());
                URLConnection uc = url.openConnection();
                uc.setRequestProperty  ("Authorization", "Basic " + encoding);
                is = uc.getInputStream();
                Log.debug("got input stream");
            }
            catch (java.net.MalformedURLException e) {
                Log.error("bad URL given: " + uri, e);
            }
            catch (java.io.FileNotFoundException e) {
                Log.error("item at URI " + uri + " not found");
            }
            catch (java.io.IOException e) {
                Log.error("IO problem for " + uri, e);
            }
            return is;
        }
        else
        {
            return super.resolveAndOpenStream(uri);
        }
    }

    private boolean _isProtectedResource(String uri)
    {
        // does this require authentication?
    }
}