Обсуждение: import_bytea function
I am trying to use the import_bytea function described in various list posts (PG version 9.3.14) in a jsp. I get an error saying that only the super user can use server-side lo_import(). If I change the Java connection to use user postgres, the function works but I would prefer not to do this. Is there a better way to update a bytea column from an uploaded file (in this case a small jpeg)? Cheers and thanks, Stephen
Stephen Davies schrieb am 07.10.2016 um 09:12:
> I am trying to use the import_bytea function described in various list posts (PG version 9.3.14) in a jsp.
>
> I get an error saying that only the super user can use server-side lo_import().
>
> If I change the Java connection to use user postgres, the function works but I would prefer not to do this.
>
> Is there a better way to update a bytea column from an uploaded file (in this case a small jpeg)?
Since you mention JSP, I assume you are using JDBC.
You can store the contents of a file in a bytea using plain JDBC no lo_import() required
String sql = "insert into images (id, image_data) values (?,?)";
Connection con = ....;
File uploaded = new File("...");
InputStream in = new FileInputStream(uploaded);
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setInt(1, 42);
pstmt.setBinaryStream(in, (int)uploaded.length());
pstmt.executeUpdate();
This *only* works with bytea column, not with "large objects".
In production code you obviously need to close all resources and handle errors.
I left that out for simplicity.
Thomas
On 07/10/16 18:48, Thomas Kellerer wrote:
> Stephen Davies schrieb am 07.10.2016 um 09:12:
>> I am trying to use the import_bytea function described in various list posts (PG version 9.3.14) in a jsp.
>>
>> I get an error saying that only the super user can use server-side lo_import().
>>
>> If I change the Java connection to use user postgres, the function works but I would prefer not to do this.
>>
>> Is there a better way to update a bytea column from an uploaded file (in this case a small jpeg)?
>
> Since you mention JSP, I assume you are using JDBC.
>
> You can store the contents of a file in a bytea using plain JDBC no lo_import() required
>
> String sql = "insert into images (id, image_data) values (?,?)";
> Connection con = ....;
> File uploaded = new File("...");
> InputStream in = new FileInputStream(uploaded);
> PreparedStatement pstmt = con.prepareStatement(sql);
> pstmt.setInt(1, 42);
> pstmt.setBinaryStream(in, (int)uploaded.length());
> pstmt.executeUpdate();
>
> This *only* works with bytea column, not with "large objects".
>
> In production code you obviously need to close all resources and handle errors.
> I left that out for simplicity.
>
> Thomas
>
>
>
>
>
That looks reasonable but I need to update rather than insert and my similar
code with sql="update part set pic=? where id=3" did not work.
Cheers,
Stephen
Stephen Davies schrieb am 07.10.2016 um 10:46:
>> You can store the contents of a file in a bytea using plain JDBC no lo_import() required
>>
>> String sql = "insert into images (id, image_data) values (?,?)";
>> Connection con = ....;
>> File uploaded = new File("...");
>> InputStream in = new FileInputStream(uploaded);
>> PreparedStatement pstmt = con.prepareStatement(sql);
>> pstmt.setInt(1, 42);
>> pstmt.setBinaryStream(in, (int)uploaded.length());
>> pstmt.executeUpdate();
>>
>> This *only* works with bytea column, not with "large objects".
>>
>> In production code you obviously need to close all resources and handle errors.
>> I left that out for simplicity.
> That looks reasonable but I need to update rather than insert and my similar
> code with sql="update part set pic=? where id=3" did not work.
That *will* work (using that myself for updates as well).
What exactly is your problem? What was the error/exception?
On 07/10/16 19:24, Thomas Kellerer wrote:
> Stephen Davies schrieb am 07.10.2016 um 10:46:
>>> You can store the contents of a file in a bytea using plain JDBC no lo_import() required
>>>
>>> String sql = "insert into images (id, image_data) values (?,?)";
>>> Connection con = ....;
>>> File uploaded = new File("...");
>>> InputStream in = new FileInputStream(uploaded);
>>> PreparedStatement pstmt = con.prepareStatement(sql);
>>> pstmt.setInt(1, 42);
>>> pstmt.setBinaryStream(in, (int)uploaded.length());
>>> pstmt.executeUpdate();
>>>
>>> This *only* works with bytea column, not with "large objects".
>>>
>>> In production code you obviously need to close all resources and handle errors.
>>> I left that out for simplicity.
>
>> That looks reasonable but I need to update rather than insert and my similar
>> code with sql="update part set pic=? where id=3" did not work.
>
> That *will* work (using that myself for updates as well).
>
> What exactly is your problem? What was the error/exception?
>
>
>
>
>
I will have to regenerate that code to get the exact error message text but it
basically said that the parameter substitution was invalid.
A follow-up question.
Once the bytea column is populated, how best to display the content in a web
page?
I have :
byte [] imgB;
ResultSet rs = st1.executeQuery("select pic from part where pno='" + p + "'");
if(rs.next()){
imgB = rs.getBytes(1);
if (imgB != null){
out.write("Content-type: image/jpeg");
out.write("Content-length: " + (int)imgB.length);
out.write(imgB.toString());
}
}
but this does not work.
The toString() looks wrong but removing it makes the write fail.
Cheers and thanks,
Stephen
--
=============================================================================
Stephen Davies Consulting P/L Phone: 08-8177 1595
Adelaide, South Australia. Mobile:040 304 0583
On 07/10/16 19:24, Thomas Kellerer wrote:
> Stephen Davies schrieb am 07.10.2016 um 10:46:
>>> You can store the contents of a file in a bytea using plain JDBC no lo_import() required
>>>
>>> String sql = "insert into images (id, image_data) values (?,?)";
>>> Connection con = ....;
>>> File uploaded = new File("...");
>>> InputStream in = new FileInputStream(uploaded);
>>> PreparedStatement pstmt = con.prepareStatement(sql);
>>> pstmt.setInt(1, 42);
>>> pstmt.setBinaryStream(in, (int)uploaded.length());
>>> pstmt.executeUpdate();
>>>
>>> This *only* works with bytea column, not with "large objects".
>>>
>>> In production code you obviously need to close all resources and handle errors.
>>> I left that out for simplicity.
>
>> That looks reasonable but I need to update rather than insert and my similar
>> code with sql="update part set pic=? where id=3" did not work.
>
> That *will* work (using that myself for updates as well).
>
> What exactly is your problem? What was the error/exception?
>
>
>
>
>
I tried the prepared statement approach again and this time it worked.
No idea what I did wrong last time.
However, my display code still does not work.
Cheers and thanks,
Stephen
Stephen Davies schrieb am 08.10.2016 um 02:57:
> A follow-up question.
> Once the bytea column is populated, how best to display the content in a web page?
>
> I have :
>
> byte [] imgB;
> ResultSet rs = st1.executeQuery("select pic from part where pno='" + p + "'");
> if(rs.next()){
> imgB = rs.getBytes(1);
> if (imgB != null){
> out.write("Content-type: image/jpeg");
> out.write("Content-length: " + (int)imgB.length);
> out.write(imgB.toString());
> }
> }
>
> but this does not work.
> The toString() looks wrong but removing it makes the write fail.
What is "out"?
(And please use a PreparedStatement to run the SELECT for security reasons)
On 2016-10-08 2:36 AM, Stephen Davies wrote:
> On 07/10/16 19:24, Thomas Kellerer wrote:
>> Stephen Davies schrieb am 07.10.2016 um 10:46:
>>>> You can store the contents of a file in a bytea using plain JDBC no
>>>> lo_import() required
>>>>
>>>> String sql = "insert into images (id, image_data) values (?,?)";
>>>> Connection con = ....;
>>>> File uploaded = new File("...");
>>>> InputStream in = new FileInputStream(uploaded);
>>>> PreparedStatement pstmt = con.prepareStatement(sql);
>>>> pstmt.setInt(1, 42);
>>>> pstmt.setBinaryStream(in, (int)uploaded.length());
>>>> pstmt.executeUpdate();
>>>>
>>>> This *only* works with bytea column, not with "large objects".
>>>>
>>>> In production code you obviously need to close all resources and
>>>> handle errors.
>>>> I left that out for simplicity.
>>
>>> That looks reasonable but I need to update rather than insert and my
>>> similar
>>> code with sql="update part set pic=? where id=3" did not work.
>>
>> That *will* work (using that myself for updates as well).
>>
>> What exactly is your problem? What was the error/exception?
>>
>>
>>
>>
>>
> I tried the prepared statement approach again and this time it worked.
> No idea what I did wrong last time.
>
> However, my display code still does not work.
You need to stream the data. Working from memory here, and it's been a
long time, but it's something like
rs = conn.executeQuery("SELECT byeta_column FROM foo WHERE bar = ?");
Blob b = (Blob) rs.getObject(1);
InputStream is = b.getInputStream();
byte[1024] bytes;
while (is.read(bytes)) {
System.out.print(String(bytes));
}
Something like this, modulo using PreparedStatements and proper use of
the byte[] buffer.
>
> Cheers and thanks,
> Stephen
>
>
Jan de Visser schrieb am 08.10.2016 um 16:11:
> You need to stream the data. Working from memory here, and it's been a long time, but it's something like
>
> rs = conn.executeQuery("SELECT byeta_column FROM foo WHERE bar = ?");
> Blob b = (Blob) rs.getObject(1);
No. getBytes() works fine with the JDBC driver.
The problem is calling toString() on it and sending that via print
Stephen Davies schrieb am 08.10.2016 um 02:57:
> I will have to regenerate that code to get the exact error message text but it basically said that the parameter
substitutionwas invalid.
>
> A follow-up question.
> Once the bytea column is populated, how best to display the content in a web page?
>
> I have :
>
> byte [] imgB;
> ResultSet rs = st1.executeQuery("select pic from part where pno='" + p + "'");
> if(rs.next()){
> imgB = rs.getBytes(1);
> if (imgB != null){
> out.write("Content-type: image/jpeg");
> out.write("Content-length: " + (int)imgB.length);
> out.write(imgB.toString());
> }
> }
>
> but this does not work.
> The toString() looks wrong but removing it makes the write fail.
Assuming you are doing this in a Servlet, you should be writing the binary data to the HttpServletResponse
Something like:
ResultSet rs = st1.executeQuery("select pic from part where pno='" + p + "'");
if (rs.next())
{
byte[] image = rs.getBytes(1);
response.setContentType("image/jpeg");
response.setIntHeader("Content-length", (int)image.length);
response.getOutputStream().write(image);
}
But this is getting quite off-topic now.
On 08/10/16 17:16, Thomas Kellerer wrote:
> Stephen Davies schrieb am 08.10.2016 um 02:57:
>> A follow-up question.
>> Once the bytea column is populated, how best to display the content in a
>> web page?
>>
>> I have :
>>
>> byte [] imgB;
>> ResultSet rs = st1.executeQuery("select pic from part where pno='" + p + "'");
>> if(rs.next()){
>> imgB = rs.getBytes(1);
>> if (imgB != null){
>> out.write("Content-type: image/jpeg");
>> out.write("Content-length: " + (int)imgB.length);
>> out.write(imgB.toString());
>> }
>> }
>>
>> but this does not work.
>> The toString() looks wrong but removing it makes the write fail.
>
> What is "out"?
>
> (And please use a PreparedStatement to run the SELECT for security reasons)
>
>
>
>
Thanks to all.
Both the update and display now work.
Cheers,
Stephen