【问题标题】:Render image from servlet in flyingsaucer generated pdf从飞碟生成的pdf中的servlet渲染图像
【发布时间】:2012-05-06 04:38:24
【问题描述】:

我正在使用 flysaucer 通过返回生成的 pdf 文档的 servlet 将 xhtml 文档呈现为 pdf。 xhtml 文档具有从另一个 servlet 请求的图像。图像 servlet 在返回适当的图像之前检查谁已登录。下面的代码显示了如何请求图像:

<img height="140" width="140" src="http://localhost:8080/myapp/servlet/DisplayPic" />

我的问题是图像的 http 请求来自 pdf 渲染器,而不是登录用户,因此图像 servlet 不知道谁已登录,因此不会返回所需的图像。

我目前正在使用下面的代码来渲染 xhtml 文档:

ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(xhtmlDocumentAsString);
renderer.layout();
os = response.getOutputStream();
renderer.createPDF(os);

我需要在请求图像 servlet 时维护用户会话,或者向渲染器提供用于该特定 xhtml 元素的图像。我认为后者可以使用ReplacedElementFactory 来完成,但我无法挖掘出任何可以帮助我的示例代码。

【问题讨论】:

标签: java pdf-generation itext flying-saucer xhtmlrenderer


【解决方案1】:

我现在已经很好地完成了这项工作。这是代码。

在我的 xhtml 文档中,我有:

<div class="profile_picture" style="display:block;width:140px;height:140px;" />

(我使用div 元素而不是img,因为工厂仅用于块级元素)

我使用以下方法渲染我的文档:

ITextRenderer renderer = new ITextRenderer();
renderer.getSharedContext().setReplacedElementFactory(new ProfileImageReplacedElementFactory(renderer.getSharedContext().getReplacedElementFactory()));
renderer.setDocumentFromString(xhtmlDocumentAsString);
renderer.layout();
os = response.getOutputStream();
renderer.createPDF(os);

我有自己的ReplacedElementFactory 如下:

public class ProfileImageReplacedElementFactory implements ReplacedElementFactory {

    private final ReplacedElementFactory superFactory;

    public ProfileImageReplacedElementFactory(ReplacedElementFactory superFactory) {
        this.superFactory = superFactory;
    }

    @Override
    public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockBox blockBox,
            UserAgentCallback userAgentCallback, int cssWidth, int cssHeight) {

        Element element = blockBox.getElement();
        if (element == null) {
            return null;
        }

        String nodeName = element.getNodeName();
        String className = element.getAttribute("class");
        if ("div".equals(nodeName) && className.contains("profile_picture")) {

            InputStream input = null;
            try {
                input = ...;
                byte[] bytes = IOUtils.toByteArray(input);
                Image image = Image.getInstance(bytes);
                FSImage fsImage = new ITextFSImage(image);

                if (fsImage != null) {
                    if ((cssWidth != -1) || (cssHeight != -1)) {
                        fsImage.scale(cssWidth, cssHeight);
                    }
                    return new ITextImageElement(fsImage);
                }
            } catch (IOException e) {
                getLogger().error(ExceptionUtils.getStackTrace(e));
            } catch (BadElementException e) {
                getLogger().error(ExceptionUtils.getStackTrace(e));
            } finally {
                IOUtils.closeQuietly(input);
            }
        }

        return superFactory.createReplacedElement(layoutContext, blockBox, userAgentCallback, cssWidth, cssHeight);
    }

    @Override
    public void reset() {
        superFactory.reset();
    }

    @Override
    public void remove(Element e) {
        superFactory.remove(e);
    }

    @Override
    public void setFormSubmissionListener(FormSubmissionListener listener) {
        superFactory.setFormSubmissionListener(listener);
    }
}

【讨论】:

  • 这适用于嵌入图像吗?一个看起来像
  • 它必须是块级元素,所以简单的答案是否定的。您可以执行类似
    之类的操作,并在 div 元素而不是 img 元素上进行替换
  • 对不起...我刚刚意识到我完全误解了你的问题。我看不出有什么不可行的原因,您只需要读取 ReplacedElementFactory 中的嵌入图像并将其返回
  • 为什么fsImage != null 在初始化后立即检查?
  • @bruno 我认为不需要...应该可以安全地忽略
猜你喜欢
  • 2012-07-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-26
  • 2013-05-14
  • 2017-11-25
  • 2014-08-13
  • 1970-01-01
  • 2019-02-04
相关资源
最近更新 更多