无法使用apache POI读取保存在postgres数据库中的xlsx文件(如bytea)

时间:2011-09-07 12:16:26

标签: java apache-poi

我正在使用apache POI读取xlsx文件并将数据上传到数据库中。我必须在Jboss上运行的调度程序(在预定的时间)完成这项工作。由于调度程序在上传的一个文件的不同服务器上运行,我使用postgres bytea数据类型使用下面的代码将文件保存在数据库中     PreparedStatement ps = con.prepareStatement(“UPDATE tk_tablename SET tk_filecolumnname =?WHERE primarykey ='”                                 + fileAttachment.getPrimaryKey()+“';” );

FilePathAssociation filePathAssociation = fileAttachment.getFilePathAssociation();

if ( filePathAssociation != null )

{

File blobFile = new File( filePathAssociation.getPhysicalFilePath() );
   FileInputStream fis = new FileInputStream( blobFile );
   ps.setBinaryStream( 1, fis, (int)blobFile.length() );
   ps.executeUpdate();
   ps.close();
   fis.close();
}

这样工作正常,文件保存在数据库中。

但是在使用以下代码在服务器上阅读文件时

ResultSet rs =
                        stmt.executeQuery( "SELECT tk_filecolumnname FROM tk_tablename WHERE primarykey = '"
                            + fileAttachment.getPrimaryKey() + "';" );
                    if ( rs != null && rs.next() )
                    {
                        InputStream fileInputStream = rs.getBinaryStream( 1 );
                        Workbook workbook = WorkbookFactory.create( fileInputStream ); // apache POI code to read a xlsx file.
                        rs.close();
                        return file;
                    }

它给出了以下错误,

java.lang.IllegalArgumentException: Your InputStream was neither an OLE2 stream, nor an OOXML stream

我知道要读取xlsx文件,POI需要OOXML支持的流。但为什么

ResultSet.getBinaryStream()

方法不会返回创建文件时保存的相同输入流。

请帮助或分享您的知识。

感谢, 艾米特。

4 个答案:

答案 0 :(得分:1)

执行以下操作:

1)断言你的代码正在从文件中正确读取工作簿(只需打开FileInputStream)。

2)一旦您的代码使用文件而不是数据库中的流,它可能与库处理流的方式相关联。您可以尝试将整个流保存到临时文件中,这也为您提供了额外的优势,您可以更快地释放数据库连接。

答案 1 :(得分:1)

1.你可能正在使用postgres 9.0。在postgres 9.0中,bytea的默认值是十六进制。在准备好的声明中简单的setByte不会工作。解决方法是编辑postgresql.conf

bytea_output = 'escape'

升级你的jdbc驱动程序也可以解决这个问题,但还没试过。

2.使用oid。这是为了将大文件存储到您的数据库。 您可以在这里找到更多信息。 http://jdbc.postgresql.org/documentation/80/binary-data.html

可以找到Java API http://jdbc.postgresql.org/documentation/publicapi/org/postgresql/largeobject/LargeObjectManager.html

答案 2 :(得分:0)

我有同样的问题(PostgreSQL配置级别的建议更改或选择新驱动程序不起作用)现在只需通过使用<将从PostgreSQL DB读取的输入流包装到缓冲的输入流中来解决它/ p>

import org.apache.commons.io.IOUtils;

IOUtils.toBufferedInputStream(file.getBinaryStream()));

希望这有帮助!

此致

Niko Wittenbeck

答案 3 :(得分:0)

确保您的类路径未被Maven过滤。 这篇文章解决了同样的问题:https://stackoverflow.com/a/13969688/704246