java - 显示数据库中的图像。获取 net.sf.jasperreports.engine.JRException : Image read failed

标签 java image jasper-reports

我正在尝试从数据库中提取图像作为二进制数据,并将其插入 Jasper Reports 报告中。

使用Jaspersoft Studio,我阅读了我的领域并将其类型更改为java.awt.Image。 然后,我将图像元素添加到报告中并将表达式更改为 ${Attr1_icon} 当我尝试编译时,我得到:

net.sf.jasperreports.engine.JRException: net.sf.jasperreports.engine.JRException: Unable to get value for field 'Attr1_icon' of class 'java.awt.Image'
at com.jaspersoft.studio.editor.preview.view.control.ReportControler.fillReport(ReportControler.java:482)
at com.jaspersoft.studio.editor.preview.view.control.ReportControler.access$18(ReportControler.java:457)
at com.jaspersoft.studio.editor.preview.view.control.ReportControler$4.run(ReportControler.java:347)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: net.sf.jasperreports.engine.JRException: Unable to get value for field 'Attr1_icon' of class 'java.awt.Image'
at net.sf.jasperreports.engine.JRResultSetDataSource.getFieldValue(JRResultSetDataSource.java:319)
at net.sf.jasperreports.engine.fill.JRFillDataset.setOldValues(JRFillDataset.java:1356)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1257)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1233)
at net.sf.jasperreports.engine.fill.JRBaseFiller.next(JRBaseFiller.java:1577)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:149)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:932)
at net.sf.jasperreports.engine.fill.BaseFillHandle$ReportFiller.run(BaseFillHandle.java:120)
at java.lang.Thread.run(Unknown Source)
Caused by: net.sf.jasperreports.engine.JRException: Image read failed.
at net.sf.jasperreports.engine.util.JRJdk14ImageReader.readImage(JRJdk14ImageReader.java:73)
at net.sf.jasperreports.engine.util.JRImageLoader.loadAwtImageFromBytes(JRImageLoader.java:167)
at net.sf.jasperreports.engine.JRResultSetDataSource.getFieldValue(JRResultSetDataSource.java:309)
Caused by: net.sf.jasperreports.engine.JRException: Image read failed.
at net.sf.jasperreports.engine.util.JRJdk14ImageReader.readImage(JRJdk14ImageReader.java:73)
at net.sf.jasperreports.engine.util.JRImageLoader.loadAwtImageFromBytes(JRImageLoader.java:167)
at net.sf.jasperreports.engine.JRResultSetDataSource.getFieldValue(JRResultSetDataSource.java:309)

导致此异常的源代码来自JRJdk14ImageReader.java中的此处:

public Image readImage(byte[] bytes) throws JRException {
    InputStream bais = new ByteArrayInputStream(bytes);

    Image image = null;
    try {
        image = ImageIO.read(bais);
    } catch (Exception e) {
        throw new JRException(e);
    } finally {
        try {
            bais.close();
        } catch (IOException e) {
        }
    }

    if (image == null) {
        throw new JRException("Image read failed."); // Line 73
    }

    return image;
}

因此,您可以看到该图像为空。但我不明白为什么。我已经验证数据确实存在。如果我将数据类型更改为字符串并将其添加到普通文本字段,它将打印二进制数据。所以,我不认为它是 null,因为传入的数据是 null。

来自Javadoc :

Returns a BufferedImage as the result of decoding a supplied InputStream with an
ImageReader chosen automatically from among those currently registered. The InputStream
is wrapped in an ImageInputStream. If no registered ImageReader claims to be able to
read the resulting stream, null is returned.

所以我猜没有注册ImageReader?我如何通过Jaspersoft Studio修复类似的问题?

编辑:我已经尝试使用 java.io.InputStream 作为建议的类类型 here但这会导致同样的错误。有点儿。一个很大的区别是,在 Jaspersoft Studio 中,您可以将图像设置为在出现错误时显示为空白。如果我使用 java.awt.Image,则此设置不会执行任何操作。我仍然收到错误,并且报告未生成。如果我使用 java.io.InputStream,报告会生成,但图像是空白的。如果我打开错误报告,我会得到类似的堆栈跟踪,但并不完全相同:

net.sf.jasperreports.engine.JRRuntimeException: net.sf.jasperreports.engine.JRException: Image read failed.
at net.sf.jasperreports.engine.export.draw.PrintDrawVisitor.visit(PrintDrawVisitor.java:143)
at net.sf.jasperreports.engine.export.draw.PrintDrawVisitor.visit(PrintDrawVisitor.java:1)
at net.sf.jasperreports.engine.fill.JRTemplatePrintImage.accept(JRTemplatePrintImage.java:451)
at net.sf.jasperreports.engine.export.draw.FrameDrawer.draw(FrameDrawer.java:251)
at net.sf.jasperreports.engine.export.draw.FrameDrawer.draw(FrameDrawer.java:199)
at net.sf.jasperreports.engine.export.JRGraphics2DExporter.exportPage(JRGraphics2DExporter.java:273)
at net.sf.jasperreports.engine.export.JRGraphics2DExporter.exportReportToGraphics2D(JRGraphics2DExporter.java:246)
at net.sf.jasperreports.engine.export.JRGraphics2DExporter.exportReport(JRGraphics2DExporter.java:184)
at net.sf.jasperreports.eclipse.viewer.ViewerCanvas.renderPage(ViewerCanvas.java:369)
at net.sf.jasperreports.eclipse.viewer.ViewerCanvas.refresh(ViewerCanvas.java:344)
at net.sf.jasperreports.eclipse.viewer.ViewerCanvas$2.viewerStateChanged(ViewerCanvas.java:118)
at net.sf.jasperreports.eclipse.viewer.ReportViewer.fireViewerModelChanged(ReportViewer.java:383)
at net.sf.jasperreports.eclipse.viewer.ReportViewer.setPageIndex(ReportViewer.java:297)
at com.jaspersoft.studio.editor.preview.view.report.swt.SWTViewer.setJRPRint(SWTViewer.java:125)
at com.jaspersoft.studio.editor.preview.view.report.swt.SWTViewer.setJRPRint(SWTViewer.java:112)
at com.jaspersoft.studio.editor.preview.PreviewJRPrint.switchRightView(PreviewJRPrint.java:226)
at com.jaspersoft.studio.editor.preview.PreviewContainer.switchRightView(PreviewContainer.java:247)
at com.jaspersoft.studio.editor.preview.PreviewJRPrint$3.switchView(PreviewJRPrint.java:194)
at com.jaspersoft.studio.editor.preview.PreviewJRPrint$1.run(PreviewJRPrint.java:153)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4144)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3761)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at com.jaspersoft.studio.rcp.intro.Application.start(Application.java:97)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
Caused by: net.sf.jasperreports.engine.JRException: Image read failed.
at net.sf.jasperreports.engine.util.JRJdk14ImageReader.readImage(JRJdk14ImageReader.java:73)
at net.sf.jasperreports.engine.util.JRImageLoader.loadAwtImageFromBytes(JRImageLoader.java:167)
at net.sf.jasperreports.engine.JRImageRenderer.getImage(JRImageRenderer.java:407)
at net.sf.jasperreports.engine.JRImageRenderer.getDimension(JRImageRenderer.java:482)
at net.sf.jasperreports.engine.RenderableUtil.getOnErrorRendererForDimension(RenderableUtil.java:264)
at net.sf.jasperreports.engine.export.draw.ImageDrawer.draw(ImageDrawer.java:116)
at net.sf.jasperreports.engine.export.draw.PrintDrawVisitor.visit(PrintDrawVisitor.java:134)

不过,如您所见,根本原因仍然来自 JRJdk14ImageReader.java 第 73 行。

其他一些可能有用的信息:

数据以长二进制形式存储在数据库中(使用 Sybase)。
图像采用 Base64 编码。

这个问题阻碍了我完成我的项目,因为截止日期很快就到了。任何帮助都会很棒。

编辑 2:我将 Jaspersoft Studio 版本从 5.5 更新到 5.6,但这没有任何作用。

同样,对于表达式我尝试了 javax.imageio.ImageIO.read($F{Attr1_icon}) 这实际上不会产生任何错误,但图像是空白的。

最佳答案

尽管我将其发布在问题中,但我完全忽略了图像是 Base64 编码的事实,这意味着它是一个字符串。事实上,Jasper 无法使用该值,因此必须对其进行解码。这可以通过以下两种方式之一完成:

将表达式更改为:

new java.io.ByteArrayInputStream(javax.xml.DatatypeConverter.parseBase64Binary($F{ImageField}))

或者简单地将字符串转换为数据库中的二进制。在 Sybase 中,这就是 base64_decode 函数。转换后,您只需将类型更改为 java.io.InputStream 即可工作。

关于java - 显示数据库中的图像。获取 net.sf.jasperreports.engine.JRException : Image read failed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24329842/

相关文章:

java - 在 Android 中使用 OpenCV 非自由模块

mysql - 无法在 iReport 中处理复杂的查询?

Java - Eclipse 编译器合规性级别 1.6 未按预期工作

java - 自定义适配器的异步行为

html - 在 CSS 中更改图像的大小

image - 如何在Word中插入图片并调整其大小?

c++ - 如何在 Leptonica 中围绕图像 (PIX) 中的矩形创建边框?

jasper-reports - 如何将 iReport 与带注释的 POJO 连接?

grails - 如何在Jasper报告中导出PDF报告

java - 德语中名词小写不正确