在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_PATH
和IMAGE_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式中:
这个代码是为我工作….