Wednesday, June 20, 2012

Jasper Reports Images in HTML PDF and XLS

One of the quickest options to get images rendered in Jasper Reports whether it is HTML, PDF or XLS is to use the "isLazy" image attribute combined with a absolute URL in the imageExpression node.

The report will render images as usual if run as XLS or PDF (embedded images) but when run as HTML the image will render from the absolute URL which is used of course in the "src" attribute.

So consider the below simple JRXML:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="remoteImage" language="groovy" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
 <property name="ireport.zoom" value="1.0"/>
 <property name="ireport.x" value="0"/>
 <property name="ireport.y" value="0"/>
 <background>
  <band splitType="Stretch"/>
 </background>
 <title>
  <band height="79" splitType="Stretch">
   <image isLazy="true">
    <reportElement x="314" y="27" width="62" height="50"/>
    <imageExpression><![CDATA["http://www.nestorurquiza.com/img/nu.png"]]></imageExpression>
   </image>
   <staticText>
    <reportElement x="106" y="51" width="151" height="20"/>
    <textElement/>
    <text><![CDATA[Here is my Logo:]]></text>
   </staticText>
  </band>
 </title>
 <pageHeader>
  <band height="35" splitType="Stretch"/>
 </pageHeader>
 <columnHeader>
  <band height="61" splitType="Stretch"/>
 </columnHeader>
 <detail>
        <band height="125" splitType="Stretch"/>
 </detail>
 <columnFooter>
  <band height="45" splitType="Stretch"/>
 </columnFooter>
 <pageFooter>
  <band height="54" splitType="Stretch"/>
 </pageFooter>
 <summary>
  <band height="42" splitType="Stretch"/>
 </summary>
</jasperReport>
It will correctly render the logo from the URL when used for any of the formats. For html in specific you will get something like:
<img src="http://www.nestorurquiza.com/img/nu.png" style="position:absolute;left:0px;top:0px;height:50px" alt=""/>
The advantage of this method besides simplicity is that static images can be kept in a central repository server which means an image change can be distributed to Jasper Reports or other pages in the web application. The typical example would be skinning a client website for which you need the logo in web pages but also in Jasper Reports.

The main disadvantage is conceptual: A report should be a snapshot and clearly a link is dynamic (the image can change any time in the future). In addition the images server has to be available for debugging purposes.

The alternative method is to not use lazy image loading in which case the image is pulled from a local path for XML and PDF but then for HTML a local servlet takes care of rendering the images which are stored previously in the user session. Here is what is needed in web.xml:
<!-- JasperReports Servlet to render local images for HTML EXporter -->
    <servlet>
        <servlet-name>JasperReportsImageServlet</servlet-name>
        <servlet-class>net.sf.jasperreports.j2ee.servlets.ImageServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>JasperReportsImageServlet</servlet-name>
        <url-pattern>/jriservlet/image</url-pattern>
    </servlet-mapping>
Here is what what is needed in your Controller when rendering XHTML/HTML Exporters:
request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "/jriservlet/image?image=");
Here is how the html source code will look like. The numbers refer to the index of images collection saved in user session:
<img src="/jriservlet/image?image=img_0_0_0" style="position:absolute;left:0px;top:0px;height:50px" alt=""/>

No comments:

Followers