Postgresql,JDBC和流式BLOB

我试图使用jdbc驱动程序从postgres数据库中检索blob。 内存太大,所以我想将其作为下载流式传输。 我尝试在ResultSet上使用getBinaryStream方法,但事实certificate这个方法实际上将它全部读入内存,因此不适用于大文件。

显然,可以在结果集上使用getBlob方法,并且可以从blob中获取输入流并从那里开始,但这就是我遇到问题的地方。

PreparedStatement ps = con.prepareStatement("select data from file_data WHERE ID = ?"); ps.setLong(1,file.fileData.id) ResultSet rs = ps.executeQuery() if(rs.next()){ rs.getBlob("data") 

那是我正在运行的代码。 当它到达最后一行时,它会抛出一个我无法理解的错误……

org.postgresql.util.PSQLException:long类型的错误值:xxxxxx

“xxxxxx”然后是文件的内容。 你可以想象这会很长,但不是真的。

我被困在这里。 有没有人对正在发生的事情有任何想法? 哎呀我甚至会采用其他方法来流式传输大型blob作为下载。

我的猜测是,你混淆了OID和BYTEA风格的blob。 大型二进制对象与Postgres中的OID列间接存储。 Postgres将实际文件数据存储在数据库表之外的某个地方。 该列只包含一个与blob内部关联的对象标识符。 例如:

 janko=# CREATE TABLE blobtest1 (name CHAR(30), image OID); CREATE TABLE janko=# INSERT INTO blobtest1 VALUES ('stackoverflow', lo_import('/tmp/stackoverflow-logo.png')); INSERT 0 1 janko=# SELECT * FROM blobtest1; name | image --------------------------------+------- stackoverflow | 16389 (1 row) 

如果使用ResultSet#getBlob(String)方法,则需要使用OID样式列。 getBlob从列中读取数据并将其转换为Long 。 然后它尝试从其内部存储中读取关联的二进制数据。

另一方面,使用BYTEA,您可以将小块二进制数据直接放在数据库中。 例如:

 janko=# CREATE TABLE blobtest2 (name CHAR(30), image BYTEA); CREATE TABLE janko=# INSERT INTO blobtest2 VALUES ('somebinary', E'\\336\\255\\276\\357\\336\\255\\276\\357'); INSERT 0 1 janko=# SELECT * FROM blobtest2; name | image --------------------------------+---------------------------------- somebinary | \336\255\276\357\336\255\276\357 (1 row) 

这里,数据列直接包含二进制数据。 如果您尝试在这样的列上使用getBlob ,数据仍将被解释为OID,但显然它不适合Long 。 让我们在数据库上尝试这个,我们刚创建:

 groovy:000> import java.sql.* ===> [import java.sql.*] groovy:000> Class.forName("org.postgresql.Driver"); ===> class org.postgresql.Driver groovy:000> db = DriverManager.getConnection("jdbc:postgresql:janko", "janko", "qwertz"); ===> org.postgresql.jdbc4.Jdbc4Connection@3a0b2c64 groovy:000> ps = db.prepareStatement("SELECT image FROM blobtest2 WHERE name = ?"); ===> SELECT image FROM blobtest2 WHERE name = ? groovy:000> ps.setString(1, "somebinary") ===> null groovy:000> rs = ps.executeQuery() ===> org.postgresql.jdbc4.Jdbc4ResultSet@66f9104a groovy:000> rs.next() ===> true groovy:000> rs.getBlob("image") ERROR org.postgresql.util.PSQLException: Bad value for type long : \336\255\276\357\336\255\276\357 at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong (AbstractJdbc2ResultSet.java:2796) at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong (AbstractJdbc2ResultSet.java:2019) at org.postgresql.jdbc4.Jdbc4ResultSet.getBlob (Jdbc4ResultSet.java:52) at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getBlob (AbstractJdbc2ResultSet.java:335) at groovysh_evaluate.run (groovysh_evaluate:3) ... 

PostgreSQL文档“存储二进制数据”会有帮助吗?

http://jdbc.postgresql.org/documentation/head/binary-data.html

标题为“从大对象中检索图像”的部分(位于页面底部)可能会有所帮助。