java - 如何在FileInputStream中加载外部图像

标签 java image inputstream flying-saucer xhtmlrenderer

我正在使用 Flying Saucer (itextrenderer)进行html到pdf转换...我必须渲染图像..我已经渲染了本地存储中的图像(它工作正常)..我必须对外部图像做同样的事情..

这是我的 html 到 pdf 图像渲染器的代码片段...

    {
        try {
            String url = new File(inputHtmlPath).toURI().toURL().toString();
            System.out.println("URL: " + url);

            OutputStream out = new FileOutputStream(outputPdfPath);
            File signUpTemplate = new File("C:/Users/SFLTP022/Desktop/task/index1.html");
            String content=FileUtils.readFileToString(signUpTemplate);
            //Flying Saucer part
            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);

            //ITextRenderer renderer = new ITextRenderer();

            renderer.setDocument(url);
            renderer.layout();
            renderer.createPDF(out);

            out.close();
        } 

这是我渲染 html 图像的默认类,我必须在其中加载外部图像


import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;

import org.apache.commons.io.IOUtils;
import org.w3c.dom.Element;
import org.xhtmlrenderer.extend.FSImage;
import org.xhtmlrenderer.extend.ReplacedElement;
import org.xhtmlrenderer.extend.ReplacedElementFactory;
import org.xhtmlrenderer.extend.UserAgentCallback;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.pdf.ITextFSImage;
import org.xhtmlrenderer.pdf.ITextImageElement;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.simple.extend.FormSubmissionListener;


import com.lowagie.text.Image;

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("https://cdn.zetran.com/testasset/images/banner/zetran/banner-parts/base/png/" + 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();
    }

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

    @Override
    public void setFormSubmissionListener(FormSubmissionListener listener) {
        // TODO Auto-generated method stub

    }
}

当我通过加载本地镜像尝试此操作时,它工作正常,如下所示

input = new FileInputStream("C:\Users\Public\Pictures\Sample Pictures\" + element.getAttribute("data-src"));

我的 html 部分(本地存储图像)看起来像

<div id="logo" class="media" data-src="Desert.jpg" style="width: 177px; height: 60px" />

我的 html 部分(外部存储图像)看起来像

<div id="logo" class="media" data-src="base.png" style="width: 177px; height: 60px" />

错误信息是

java.lang.RuntimeException: There was a problem trying to read a template embedded graphic.
    at com.boot.MediaReplacedElementFactory.createReplacedElement(MediaReplacedElementFactory.java:56)
    at org.xhtmlrenderer.render.BlockBox.calcDimensions(BlockBox.java:716)
    at org.xhtmlrenderer.render.BlockBox.calcDimensions(BlockBox.java:666)
    at org.xhtmlrenderer.render.BlockBox.collapseBottomMargin(BlockBox.java:1205)
    at org.xhtmlrenderer.render.BlockBox.collapseBottomMargin(BlockBox.java:1228)
    at org.xhtmlrenderer.render.BlockBox.collapseMargins(BlockBox.java:1126)
    at org.xhtmlrenderer.render.BlockBox.layout(BlockBox.java:811)
    at org.xhtmlrenderer.render.BlockBox.layout(BlockBox.java:776)
    at org.xhtmlrenderer.layout.BlockBoxing.layoutBlockChild0(BlockBoxing.java:321)
    at org.xhtmlrenderer.layout.BlockBoxing.layoutBlockChild(BlockBoxing.java:299)
    at org.xhtmlrenderer.layout.BlockBoxing.layoutContent(BlockBoxing.java:90)
    at org.xhtmlrenderer.render.BlockBox.layoutChildren(BlockBox.java:967)
    at org.xhtmlrenderer.render.BlockBox.layout(BlockBox.java:847)
    at org.xhtmlrenderer.render.BlockBox.layout(BlockBox.java:776)
    at org.xhtmlrenderer.pdf.ITextRenderer.layout(ITextRenderer.java:229)
    at com.boot.App6.generatePDF(App6.java:67)
    at com.boot.App6.main(App6.java:27)
Caused by: java.io.FileNotFoundException: https:\cdn.zetran.com\testasset\images\banner\zetran\banner-parts\base\png\base.png (The filename, directory name, or volume label syntax is incorrect)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at com.boot.MediaReplacedElementFactory.createReplacedElement(MediaReplacedElementFactory.java:45)

最佳答案

是的,您可以将文件路径写为 URL,例如file://....,但 FileInputStream 只能处理那些指向本地文件的文件协议(protocol) URL。 Http-URL 必须使用某种 HTTP 客户端加载。

关于java - 如何在FileInputStream中加载外部图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56273306/

相关文章:

Java使用扫描仪输入键按下

c - 设备内部的共享内存声明

html - 为什么图像在 MAC 上不占据浏览器的整个宽度?

c++ - winapi编程中工具栏自定义图标的使用方法

java - java中线程安全的InputStream

java - 递归读取文件夹中的所有文件Java

java - 从 JButton ActionListener 填充 JList

java - 如何查找java项目中未使用/死的代码

java - 连续逐渐将背景颜色更改为所有颜色

java - 为什么我的 ByteArrayInputStream 在从任何字符串创建后为空?