使用Flying Saucer将图像渲染为PDF格式的内存 [英] Using Flying Saucer to Render Images to PDF In Memory

查看:173
本文介绍了使用Flying Saucer将图像渲染为PDF格式的内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Flying Saucer将XHTML转换为PDF文档。我已经得到了只使用基本HTML和内联CSS的代码,但是,现在我正在尝试将图像作为一种标题添加到PDF中。我想知道的是,如果有任何方式通过在图像文件中读取Java Image对象来添加图像,然后以某种方式将其添加到PDF(或XHTML - 就像它获取虚拟url一样表示我可以用来渲染PDF的Image对象。有没有人做过这样的事情?

I'm using Flying Saucer to convert XHTML to a PDF document. I've gotten the code to work with just basic HTML and in-line CSS, however, now I'm attempting to add an image as a sort of header to the PDF. What I'm wondering is if there is any way whatsoever to add the image by reading in an image file as a Java Image object, then adding that somehow to the PDF (or to the XHTML -- like it gets a virtual "url" representing the Image object that I can use to render the PDF). Has anyone ever done anything like this?

提前感谢您提供的任何帮助!

Thanks in advance for any help you can provide!

推荐答案

上周我必须这样做,希望我能马上回答你。

I had to do that last week so hopefully I will be able to answer you right away.

最简单的方法是在使用Flying Saucer渲染之前,在HTML模板中添加想要的图像作为标记。在Flying Saucer中,您必须实现 ReplacedElementFactory ,以便在使用图像数据渲染之前替换任何标记。

The easiest way is to add the image you want as markup in your HTML template before rendering with Flying Saucer. Within Flying Saucer you will have to implement a ReplacedElementFactory so that you can replace any markup before rendering with the image data.

/**
 * Replaced element in order to replace elements like 
 * <tt>&lt;div class="media" data-src="image.png" /></tt> with the real
 * media content.
 */
public class MediaReplacedElementFactory implements ReplacedElementFactory {
    private final ReplacedElementFactory superFactory;

    public MediaReplacedElementFactory(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");
        // Replace any <div class="media" data-src="image.png" /> with the
        // binary data of `image.png` into the PDF.
        if ("div".equals(nodeName) && "media".equals(className)) {
            if (!element.hasAttribute("data-src")) {
                throw new RuntimeException("An element with class `media` is missing a `data-src` attribute indicating the media file.");
            }
            InputStream input = null;
            try {
                input = new FileInputStream("/base/folder/" + element.getAttribute("data-src"));
                final byte[] bytes = IOUtils.toByteArray(input);
                final Image image = Image.getInstance(bytes);
                final FSImage fsImage = new ITextFSImage(image);
                if (fsImage != null) {
                    if ((cssWidth != -1) || (cssHeight != -1)) {
                        fsImage.scale(cssWidth, cssHeight);
                    }
                    return new ITextImageElement(fsImage);
                }
            } catch (Exception e) {
                throw new RuntimeException("There was a problem trying to read a template embedded graphic.", e);
            } finally {
                IOUtils.closeQuietly(input);
            }
        }
        return this.superFactory.createReplacedElement(layoutContext, blockBox, userAgentCallback, cssWidth, cssHeight);
    }

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

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

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

你会注意到我在这里有硬编码 / base / folder 这是HTML文件所在的文件夹,因为它将成为Flying Saucer解析媒体的根网址。您可以将它更改为正确的位置,来自您想要的任何地方(例如属性)。

You will notice that I have hardcoded here /base/folder which is the folder where the HTML file is located as it will be the root url for Flying Saucer for resolving medias. You may change it to the correct location, coming from anywhere you want (Properties for example).

在您的HTML标记中,您指示< div class =mediadata-src =somefile.png/> ,如下所示:

Within your HTML markup you indicate somewhere a <div class="media" data-src="somefile.png" /> like so:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>My document</title>
        <style type="text/css">
        #logo { /* something if needed */ }
        </style>
    </head>
    <body>
        <!-- Header -->
        <div id="logo" class="media" data-src="media/logo.png" style="width: 177px; height: 60px" />
        ...
    </body>
</html>



渲染



最后你只需要在渲染时向Flying-Saucer表明你的 ReplacedElementFactory

String content = loadHtml();
ITextRenderer renderer = new ITextRenderer();
renderer.getSharedContext().setReplacedElementFactory(new MediaReplacedElementFactory(renderer.getSharedContext().getReplacedElementFactory()));
renderer.setDocumentFromString(content.toString());
renderer.layout();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
renderer.createPDF(baos);
// baos.toByteArray();

我一直在使用Freemarker从模板生成HTML,然后将结果反馈给FlyingSaucer成功。这是一个非常整洁的图书馆。

I have been using Freemarker to generate the HTML from a template and then feeding the result to FlyingSaucer with great success. This is a pretty neat library.

这篇关于使用Flying Saucer将图像渲染为PDF格式的内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆