在JasperReport中将字节数组显示为图像

我有一个图像保存为一个byte[] ,我想在JasperReport中显示它的图像。 我试图从Java方法获取数据:

 public InputStream getImage(){ return new ByteArrayInputStream(getImageByteArray()); } 

 public Image getImage() throws IOException{ return ImageIO.read(new ByteArrayInputStream(getImageByteArray())); } 

 public String getImage(){ return new String((new org.apache.commons.codec.binary.Base64()).encode(getImageByteArray())); } 

但他们似乎都没有工作。

jrxml看起来像这样:

 <image hAlign="Center" vAlign="Middle" isUsingCache="true" isLazy="true"> <reportElement positionType="Float" x="0" y="0" width="164" height="32" isRemoveLineWhenBlank="true" isPrintWhenDetailOverflows="true" uuid="c63c84a8-41c7-4ca3-8451-751d43fa8a9e"/> <imageExpression><![CDATA[$P{paramObject}.getImage()]]></imageExpression> </image> 

我尝试的一些东西得到exception,一些打印JasperReport,但图像应该是空白区域。 我知道图像数据在那里,因为我可以在JSF页面中显示它。 图像数据是SVG数据。

自定义图像代码转换器

编写一个自定义的图像代码转换器,可以读取一个SVG文件,并将该资源转换为PNG或SVG文件。 以PDF格式导出时,可以直接使用SVG文件。 考虑:

 import java.awt.Color; import java.io.*; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.util.JRLoader; import org.apache.batik.transcoder.*; import static org.apache.batik.transcoder.image.ImageTranscoder.*; import org.apache.batik.transcoder.image.PNGTranscoder; public class ImageTranscoder { public static InputStream asSVG(final String file) throws JRException { return new ByteArrayInputStream(load(file)); } public static InputStream asPNG(final String file) throws TranscoderException, JRException { return asPNG(load(file)); } public static InputStream asPNG(final byte[] svg) throws TranscoderException { final ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); final ByteArrayInputStream inBytes = new ByteArrayInputStream(svg); final TranscoderInput input = new TranscoderInput(inBytes); final TranscoderOutput output = new TranscoderOutput(outBytes); final PNGTranscoder transcoder = new PNGTranscoder(); transcoder.addTranscodingHint(KEY_BACKGROUND_COLOR, Color.white); transcoder.addTranscodingHint(KEY_FORCE_TRANSPARENT_WHITE, true); transcoder.transcode(input, output); final byte[] bytes = outBytes.toByteArray(); return new ByteArrayInputStream(bytes); } private static byte[] load(final String file) throws JRException { return JRLoader.loadBytesFromResource(file); } } 

导入转码器

在JRXML文件中,导入完全限定的类:

 <import value="com.company.jasper.ImageTranscoder"/> 

应用图像转码器

按照惯例,将调色板中的图像拖放到报告上。 将其expression式设置为:

 ImageTranscoder.asSVG($P{IMAGES_PATH} + $P{IMAGE_FILENAME} + ".svg") 

如果你绝对需要一个PNG版本,那么就可以对其进行转码:

 ImageTranscoder.asPNG($P{IMAGES_PATH} + $P{IMAGE_FILENAME} + ".svg") 

HTML和PDF

使用HTML,通常PNG图像仍然是首选。 您可以采取多种方法将HTML(PNG)与PDF(SVG)区分开来。 一个简单的方法是将两个不同的键值分配给两个不同的图像元素。 例如:

 <image scaleImage="RetainShape" onErrorType="Blank"> <reportElement key="IMAGE_PNG"/> <imageExpression><![CDATA[ImageTranscoder.asPNG(...)]]></imageExpression> </image> <image scaleImage="RetainShape" onErrorType="Blank"> <reportElement key="IMAGE_SVG"/> <imageExpression><![CDATA[ImageTranscoder.asSVG(...)]]></imageExpression> </image> 

然后,您可以根据导出types排除一个或另一个:

 <property name="net.sf.jasperreports.export.html.exclude.key.IMAGE_SVG"/> <property name="net.sf.jasperreports.export.pdf.exclude.key.IMAGE_PNG"/> 

概要

虽然包含PNG图像更简单,但从SVG转换PNG图像是可以避免的额外步骤。 由于JasperReports库使用蜡染引擎渲染图像,因此在生成报告时利用它将SVG文件转换为PNG。

这样,无论在报告中是使用PNG还是SVG文件,SVG都可以作为所有格式的单一来源。

确保适当地设置IMAGES_PATHIMAGE_FILENAME参数。

HTML和Base64

强制图像embedded使用:

 <property name="net.sf.jasperreports.export.html.embed.image" value="true"/> 

PNG图像变成Base64编码的string:

 <img src="data:image/png;base64,..."/> 

这将使报表加载速度更快(对图像没有额外的HTTP请求),并简化了体系结构,因为它消除了外部依赖性。 也就是说,Web服务器不再需要提供图像,因为它完全embedded。

假设你有图像字节编码base64,你可以使用以下

 <image> <reportElement/> <imageExpression> <![CDATA[javax.imageio.ImageIO.read(new java.io.ByteArrayInputStream(new sun.misc.BASE64Decoder().decodeBuffer("/9j/4AAQ .... "))) ]]> </imageExpression> </image> 

你可以试试这个:

将您的图像参数(这里是img )设置为InputStream

 <parameter name="img" class="java.io.InputStream"> <parameterDescription><![CDATA[]]></parameterDescription> </parameter> 

然后设置onErrorType =“空白”您的图像元素(其实不知道这个原因:))

 <image onErrorType="Blank"> <reportElement x="2" y="4" width="119" height="62" uuid="66857471-6aa2-4ff0-be59-e2e1b0214bfc"/> <imageExpression><![CDATA[$P{img}]]></imageExpression> </image> 

我提出一个简单的解决scheme 它工作,我正在使用它。 这样我们就避免了中间代码和修改我们的应用程序。

我们必须build立以下导入:

 <import value="javax.swing.ImageIcon"/> 

我们的图像领域的定义必须是Objettypes的:

 <field name="myImage" class="java.lang.Object"/> 

然后在报告的正文中,我们必须把图像放在下面的expression式中:

 <image> <reportElement x="10" y="10" width="100" height="100" uuid="a791129e-a20d-4be3-bdcd-27528bf2edc4"/> <imageExpression><![CDATA[(new ImageIcon((byte[])$F{foto})).getImage()]]></imageExpression> </image> 

就这些。 解决scheme如何工作? 我们导入javax.swing.ImageIcon库,它允许我们从byte[]创build一个新的ImageIcon,然后我们可以使用getImage()ImageIcon转换为Image

我们的图像领域的定义必须是Objettypes的:

然后在报告的正文中,我们必须把图像放在下面的expression式中:

这个代码是为我工作….