2014-06-20 162 views
2

我试图从我的数据库中以二进制数据的形式提取图像,并将其插入到Jasper Reports报告中。从数据库中显示图像。获取net.sf.jasperreports.engine.JRException:图像读取失败

使用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; 
} 

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

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

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

数据作为LONG BINARY(使用Sybase)存储在数据库中。
图像是base64编码的。

这个问题阻止我完成我的项目,截止日期接近相当快。任何帮助都会很棒。

编辑2:我更新了我的版本Jaspersoft Studio从5.5到5.6,但没有做任何事情。

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

回答

2

尽管我在问题中发布了它,但我完全忽略了图像是Base64编码的事实,这意味着它是一个字符串。因为Jasper不能使用这个值,所以它必须被解码。这可以通过以下两种方法之一:

更改表达式:

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

或简单地转换在数据库为二进制字符串。在Sybase中,这是base64_decode函数。一旦它被转换,您可以简单地将类型更改为java.io.InputStream,它会起作用。