1

I am working in html to pdf conversion using flying saucer(itextrenderer)...I have to render image..I have rendered the image which was in my local storage(it works fine)..I have to do the same thing with external image..

Here is my code snippet for html to pdf image renderer...

    {
        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();
        } 

Here is my default class to render html image,in which i have to load external image


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

    }
}

When i tried this by loading local image it works fine,as shown below

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

My html part(local storage image) looks like

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

My html part(External storage image) looks like

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

The error message is

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)
sujirajan
  • 11
  • 3
  • 1
    You are trying to load from a URL using a FileInputStream `new FileInputStream("https://cdn.zetran.com/testasset/images/banner/zetran/banner-parts/base/png/" + element.getAttribute("data-src"));` - a URL is not a file... you might want to use ImageIO instead https://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html – BretC May 23 '19 at 10:43

1 Answers1

0

Yes, you can write file paths as URLs, e.g. file://...., but FileInputStream can only handle those kind of file-protocol-URLs pointing to a local file. Http-URLs must be loaded with some kind of HTTP Client.

Mick
  • 954
  • 7
  • 17