Postgresql、JDBC 和流式 BLOB
我正在尝试使用 jdbc 驱动程序从 postgres 数据库中检索 blob。它太大了,无法存储在内存中,因此我想将其作为下载流式传输。我尝试在 ResultSet 上使用 getBinaryStream 方法,但事实证明该方法实际上将其全部读取到内存中,因此不适用于大文件。
显然,可以在结果集上使用 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" 那么是文件的内容。你可以想象这会很长,但这并不是重点。
我被困在这里了。有人对发生的事情有任何想法吗?哎呀,我什至会采取替代方法来下载大块的流。
I am trying to retrieve a blob from a postgres database using the jdbc drivers. It is too big to have in memory so I want to stream it as a download. I tried using the getBinaryStream method on ResultSet, but it turns out that this method actually reads it all into memory, so doesn't work for large file.
Apparently, one can use the getBlob method on the resultset and the presumeably get the inputstream from the blob and go from there, but that is where I run into my problem.
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")
That is the code I'm running. When it gets to that last line it throw out an error that I cannot make sense of...
org.postgresql.util.PSQLException: Bad value for type long : xxxxxx
"xxxxxx" then is the contents of the file. You can imagine that gets quite long, but not really the point.
I'm stuck here. Does anyone have any ideas on what is going on? Heck I'll even take alternative methods for streaming large blobs as a download.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的猜测是,您混淆了 OID 和 BYTEA 风格的 blob。大型二进制对象在 Postgres 中通过 OID 列间接存储。实际的文件数据由 Postgres 存储在数据库表之外的某个位置。该列仅包含与 blob 内部关联的对象标识符。例如:
如果您使用
ResultSet#getBlob(String)
方法,则需要 OID 样式列。getBlob
从列中读取数据并将其转换为Long
。然后它尝试从其内部存储读取关联的二进制数据。另一方面,使用 BYTEA,您可以将小块二进制数据直接放入数据库中。例如:
这里,数据列直接包含二进制数据。如果您尝试在此类列上使用
getBlob
,数据仍将被解释为 OID,但显然它不适合Long
。让我们在刚刚创建的数据库上尝试一下:My guess is, that you have mixed up OID and BYTEA style blobs. Large binary objects are stored indirecty with OID columns in Postgres. The actual file data is stored somewhere outside the database table by Postgres. The column just contains an object identifier that is associated internally with the blob. For instance:
If you use the
ResultSet#getBlob(String)
method, than an OID style column is expected.getBlob
reads the data from the column and converts it to aLong
. Then it tries to read the associated binary data from its internal storage.On the other hand, with BYTEA you can place small pieces of binary data directly in your DB. For instance:
Here, the data column directly contains the binary data. If you try to use
getBlob
on such a column, the data will still be interpreted as an OID but obviously it will not fit into aLong
. Let's try this on the database, we just created:PostgreSQL 文档“存储二进制数据”有帮助吗?
https://jdbc.postgresql.org/documentation/binary-data/
页面底部标题为“从大对象中检索图像”的部分可能会有所帮助。
Would the PostgreSQL docs for "Storing Binary Data" help?
https://jdbc.postgresql.org/documentation/binary-data/
The section titled "Retrieving the image from the Large Object", its at the bottom of the page, might help.