How to show an image on jasper report?

2019-01-07 06:46发布

问题:

I want to show an image on a jasper report. I have the following on the .jrxml:

<image>
  <reportElement x="181" y="0" width="209" height="74"/>
  <imageExpression class="java.lang.String"><![CDATA["logo.jpg"]]></imageExpression>
</image>

The image logo.jpg is in the same directory as the .jrxml. By just putting that it didn't work for me. I googled a bit and found out that jasper report considers what i put on the .jrxml as a relative path to the JVM directory and that to change this I need to pass as a "REPORT_FILE_RESOLVER" parameter a FileResolver that returns the file. So, I did the following in my .java (is located in same place as the .jrxml and the image)

FileResolver fileResolver = new FileResolver() {

 @Override
 public File resolveFile(String fileName) {
  return new File(fileName);
 }
};
HashMap<String, Object> parameters = new HashMap<String, Object>();

parameters.put("REPORT_FILE_RESOLVER", fileResolver);
...

Which should return the expected file, but I still get a

net.sf.jasperreports.engine.JRException: Error loading byte data : logo.jpg
    at net.sf.jasperreports.engine.util.JRLoader.loadBytes(JRLoader.java:301)
    at net.sf.jasperreports.engine.util.JRLoader.loadBytesFromLocation(JRLoader.java:479)
    at net.sf.jasperreports.engine.JRImageRenderer.getInstance(JRImageRenderer.java:180)
...

What am I doing wrong?

Thanks!

回答1:

I've made this work by passing a parameter specifying the absolute location of the file:

<imageExpression class="java.lang.String">
      <![CDATA[$P{REPORTS_DIR} + "/images/logo.jpg"]]>
</imageExpression>


回答2:

I do it this way - image is passed by path:

HashMap<String, Object> params = new HashMap<String, Object>();
params.put("logo", ClassLoader.getSystemResource("logo.jpg").getPath());

.jrxml

<parameter name="logo" class="java.lang.String"/>
...
<image>
    <reportElement x="0" y="1" width="100" height="37"/>
    <imageExpression><![CDATA[$P{logo}]]></imageExpression>
</image>

...or image is passed as InputStream (I don't know why, but <image> need to have onErrorType attribute set to "Blank", otherwise it does not work - throws exception):

HashMap<String, Object> params = new HashMap<String, Object>();
params.put("logo", ClassLoader.getSystemResourceAsStream("logo.jpg"));

.jrxml

<parameter name="logo" class="java.io.InputStream"/>
...
<image onErrorType="Blank">
    <reportElement x="0" y="1" width="100" height="37"/>
    <imageExpression><![CDATA[$P{logo}]]></imageExpression>
</image>


回答3:

Here was the problem:

As I said previously I have in the same directory the .jrxml, the logo.jpg and the .java that uses the .jrxml.

The thing is that the fileResolver

FileResolver fileResolver = new FileResolver() {

 @Override
 public File resolveFile(String fileName) {
  return new File(fileName);
 }
};

didn't returned the image file. I found out it mapped on to a different directory and not the one I was expecting. So, I changed it to:

FileResolver fileResolver = new FileResolver() {

     @Override
     public File resolveFile(String fileName) {
        URI uri;
        try {
          uri = new URI(this.getClass().getResource(fileName).getPath());
          return new File(uri.getPath());
        } catch (URISyntaxException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          return null;
        }
    }
};

And that worked out. I forgot the fact that:

A relative pathname, in contrast, must be interpreted in terms of information taken from some other pathname. By default the classes in the java.io package always resolve relative pathnames against the current user directory. This directory is named by the system property user.dir, and is typically the directory in which the Java virtual machine was invoked.

(taken from the java api - File (Java Platform SE 6))

The directory in which the JVM is invoked is not the one I have all this data.

Thanks!



回答4:

Try declaring a param such as myImg of type InputStream in your report page. Declare this type both for param and image placeholder on page. Then, grab the image from classpath using something like (assuming image name is 'imgName.ext' and it is in the package named 'your.package')

InputStream imgInputStream = 
    this.getClass().getResourceAsStream("/your/package/imgName.ext");
parameters.put("myImg", imgInputStream);