java 在飞碟生成的 pdf 中渲染来自 servlet 的图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10316607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:32:37  来源:igfitidea点击:

Render image from servlet in flyingsaucer generated pdf

javapdf-generationitextflying-saucerxhtmlrenderer

提问by Edd

I'm using flyingsaucer to render an xhtml document to pdf through a servlet which returns the generated pdf document. The xhtml document features an image which is requested from another servlet. The image servlet checks who is logged in before returning the appropriate image. The code below shows how the image is requested:

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

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

My problem is that the http request for the image is from the pdf renderer and not the logged in user so the image servlet doesn't know who's logged in and therefore the desired image is not returned.

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

I'm currently using the code below to render the xhtml document:

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

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

I need to either maintain the user's session when the image servlet is requested or provide the renderer with the image to use for that specific xhtml element. I think the latter can be done using a ReplacedElementFactorybut I haven't been able to dig out any example code that can help me.

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

回答by Edd

I've got this working very nicely now. Here's the code.

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

In my xhtml document i have:

在我的 xhtml 文档中,我有:

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

(I'm using a divelement instead of imgas the factory is only used for block level elements)

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

I render my document using:

我使用以下方法呈现我的文档:

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

And i have my own ReplacedElementFactoryas below:

我有我自己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);
    }
}