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
Render image from servlet in flyingsaucer generated pdf
提问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 ReplacedElementFactory
but 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 div
element instead of img
as 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 ReplacedElementFactory
as 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);
}
}