HTML embedded images in PDF

sweetas
edited February 11, 2022 in Analytics #1
<p style="font-size:15px;font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;">I created a report using BIRT and some dynamic fields are HTML values, which come from backend systems, but when I try to generate a PDF report with HTML embedded image - then it shows: "The resource of this report item is not reachable." instead of image.</p>
<p style="font-size:15px;font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;">Is there any solution to render embedded image in PDF? It works fine in HTML.</p>

Comments

  • <div>I found a solution, how to render images in PDF, which are embedded in HTML content. The problem was with BIRT library ResourceLocatorWrapper class. I changed method: </div>
    <div> </div>
    <div>
    <blockquote class="ipsBlockquote">
    <p> </p>
    <p>public byte[] findResource(ModuleHandle design, String fileName, int fileType, Map appContext);</p>
    </blockquote>
    <p> </p>
    </div>
    <div> </div>
    <div>Now it successfully shows embedded images and rest HTML content in PDF. It is not needed to add this in BIRT jar library, you could add this class in your project under org.eclipse.birt.report.engine.util package, as I did, and it should work fine.</div>
    <div> </div>
    <div>
    <pre class="_prettyXprint">
    /*******************************************************************************
    * Copyright (c) 2005,2010 Actuate Corporation.
    * All rights reserved. This program and the accompanying materials
    * are made available under the terms of the Eclipse Public License v1.0
    * which accompanies this distribution, and is available at
    * http://www.eclipse.org/legal/epl-v10.html
    *
    * Contributors:
    * Actuate Corporation - initial API and implementation
    *******************************************************************************/

    package org.eclipse.birt.report.engine.util;

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    import org.eclipse.birt.report.engine.i18n.MessageConstants;
    import org.eclipse.birt.report.model.api.ModuleHandle;

    import com.lowagie.text.ExceptionConverter;
    import com.lowagie.text.pdf.codec.Base64;

    public class ResourceLocatorWrapper {

    private HashMap<URL, byte[]> cache;
    private static final byte[] DUMMY_BYTES = new byte[0];
    private static final String RESOURCE_BUNDLE = "org.eclipse.birt.report.engine.i18n.Messages";
    protected static Logger logger = Logger.getLogger(ResourceLocatorWrapper.class.getName(), RESOURCE_BUNDLE);

    public ResourceLocatorWrapper() {
    cache = new HashMap<URL, byte[]>();
    }

    public void dispose() {
    synchronized (cache) {
    cache.clear();
    cache = null;
    }
    }

    /**
    *
    * @param fileName
    * @param fileType
    * @param appContext
    * @return
    */
    public byte[] findResource(ModuleHandle design, String fileName, int fileType, Map appContext) {

    if (fileName.startsWith("data:")) {
    final String base64Data = fileName.substring(fileName.indexOf(",") + 1);
    try {
    return Base64.decode(base64Data);
    } catch (Exception e) {
    throw new ExceptionConverter(e);
    }
    } else {
    URL url = design.findResource(fileName, fileType, appContext);
    if (url == null) {
    logger.log(Level.WARNING, MessageConstants.RESOURCE_NOT_ACCESSIBLE, fileName);
    return DUMMY_BYTES;
    }
    return findResource(url);
    }
    }

    /**
    * Finds a resource from the given URL. If the URL is not accessible, it
    * will return a 0-size byte array.
    */
    public byte[] findResource(URL url) {
    System.out.println("findResource(URL url)");
    if (url == null) {
    return DUMMY_BYTES;
    }
    synchronized (cache) {
    if (cache == null) {
    return DUMMY_BYTES;
    }
    byte[] inBytes = cache.get(url);
    if (inBytes == null) {
    try {
    InputStream in = url.openStream();
    inBytes = getByteArrayFromInputStream(in);
    in.close();
    cache.put(url, inBytes);
    } catch (IOException e) {
    logger.log(Level.WARNING, MessageConstants.RESOURCE_NOT_ACCESSIBLE, url.toExternalForm());
    cache.put(url, DUMMY_BYTES);
    return DUMMY_BYTES;
    }
    }
    return inBytes;
    }
    }

    private byte[] getByteArrayFromInputStream(InputStream in) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int size = in.read(buffer);
    while (size != -1) {
    out.write(buffer, 0, size);
    size = in.read(buffer);
    }
    buffer = out.toByteArray();
    out.close();
    return buffer;
    }

    }

    </pre>
    </div>
    <div> </div>
  • <p>Hi Sweetas! </p>
    <p>thank you for your help, could you please provide a .rpt example??</p>
    <p>Thank you very much!</p>
    <p>MC</p>
  • <p>Hi,</p>
    <p> </p>
    <p>Can you please provide  a sample rptdesign for the above.</p>
  • <p>Hello Sweetas,</p>
    <p> </p>
    <p>I have tried to create this java file into my jar file with same package name given in your java code.</p>
    <p> </p>
    <p>When try to execute the BIRT Report now I am getting the following security exception. How do we resolve this??</p>
    <p> </p>
    <div>java.lang.SecurityException: class "org.eclipse.birt.report.engine.util.ResourceLocatorWrapper"'s signer information does not match signer information of other classes in the same package</div>
    <div>at java.lang.ClassLoader.checkCerts(ClassLoader.java:895)</div>
    <div>at java.lang.ClassLoader.preDefineClass(ClassLoader.java:665)</div>
    <div>at java.lang.ClassLoader.defineClass(ClassLoader.java:758)</div>
    <div>at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)</div>
    <div>at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)</div>
    <div>at java.net.URLClassLoader.access$100(URLClassLoader.java:73)</div>
    <div>at java.net.URLClassLoader$1.run(URLClassLoader.java:368)</div>
    <div>at java.net.URLClassLoader$1.run(URLClassLoader.java:362)</div>
    <div>at java.security.AccessController.doPrivileged(Native Method)</div>
    <div>at java.net.URLClassLoader.findClass(URLClassLoader.java:361)</div>
    <div>at java.lang.ClassLoader.loadClass(ClassLoader.java:424)</div>
    <div>at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)</div>
    <div>at java.lang.ClassLoader.loadClass(ClassLoader.java:357)</div>
    <div>at org.eclipse.birt.report.engine.api.impl.EngineTask.<init>(EngineTask.java:240)</div>
    <div>at org.eclipse.birt.report.engine.api.impl.EngineTask.<init>(EngineTask.java:223)</div>
    <div>at org.eclipse.birt.report.engine.api.impl.RunAndRenderTask.<init>(RunAndRenderTask.java:57)</div>
    <div>at org.eclipse.birt.report.engine.api.impl.ReportEngineHelper.createRunAndRenderTask(ReportEngineHelper.java:311)</div>
    <div>at org.eclipse.birt.report.engine.api.impl.ReportEngine.createRunAndRenderTask(ReportEngine.java:374)</div>
    <p> </p>
    <p>Regards,</p>
    <p>Koti</p>
  • JokerNotClown
    edited July 23, 2018 #7

    In my case I'm not using BD to get the data, so I send the HTML to BIRT with a parameter.

    In result I get one generated pdf, with errors "The resource of this report item is not reachable."

    So the framework does not decode Base64 images like many people have written in this forum

    Solutions I already try and questions:

    • JFreeman, this your solutions just work when I have a table with images, I think, so if I'm wrong correct me pls
    • sweetas, this solution make me change the library, if I don't do it, I will get the same error then Koti.

    I need more solutions :/

    Thanks