问题
I tried to implement file store in PostgreSQL using OID:
public void upload() throws SQLException, GSSException
{
if (file != null)
{
try
{
InputStream inputStream = file.getInputStream();
Connection conn = ds.getConnection();
PreparedStatement ps = null;
boolean committed = false;
try
{
conn.setAutoCommit(false);
ps = conn.prepareStatement("INSERT INTO PROCEDURE_FILES (ID, PROCEDURE_ID, FILE_NAME, FILE) "
+ " VALUES (?, ?, ?, ?)");
ps.setInt(1, obj.number);
ps.setInt(2, obj.number);
ps.setString(3, file.getSubmittedFileName());
ps.setBlob(4, inputStream, inputStream.available());
ps.executeUpdate();
ps.close();
conn.commit();
committed = true;
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
if (!committed)
{
conn.rollback();
}
if (ps != null)
{
ps.close();
}
conn.close();
}
}
catch (IOException e)
{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Upload failed!"));
}
}
}
public void initFileDBData() throws SQLException, IOException
{
Connection conn = ds.getConnection();
PreparedStatement ps = null;
try
{
conn.setAutoCommit(false);
ps = conn.prepareStatement("SELECT * FROM PROCEDURE_FILES WHERE ID = ?");
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
while (rs.next())
{
String file_name = rs.getString("FILE_NAME");
Blob oid = rs.getBlob("FILE");
InputStream binaryStreasm = oid.getBinaryStream();
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentLength(binaryStreasm.available());
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + file_name + "\"");
byte[] buf;
buf = new byte[binaryStreasm.available()];
int offset = 0;
int numRead = 0;
while ((offset < buf.length) && ((numRead = binaryStreasm.read(buf, offset, buf.length - offset)) >= 0))
{
offset += numRead;
}
HttpServletResponse response
= (HttpServletResponse) FacesContext.getCurrentInstance()
.getExternalContext().getResponse();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + file_name);
response.getOutputStream().write(buf);
response.getOutputStream().flush();
response.getOutputStream().close();
FacesContext.getCurrentInstance().responseComplete();
}
}
finally
{
if (ps != null)
{
ps.close();
}
conn.close();
}
}
But when I try to download the file I always get file with size 0 bytes. How I can fix this problem?
I suppose that I'm not downloading the the file in a proper way?
回答1:
Peter, this worked for me with PostgreSQL 9.3 and Java OpenJDK 7.
Writing with LargeObjectAPI:
public static void main(String[] args) throws SQLException, FileNotFoundException, IOException {
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test01", "postgres", "postgres");
conn.setAutoCommit(false);
File file = new File("/home/user/Pictures/somePicture.jpg");
FileInputStream fis = new FileInputStream(file);
LargeObjectManager lom = PGConnection.class.cast(conn).getLargeObjectAPI();
long oid = lom.createLO(LargeObjectManager.READ | LargeObjectManager.WRITE);
LargeObject lob = lom.open(oid, LargeObjectManager.WRITE);
byte[] buffer = new byte[2048];
int s = 0;
while ((s = fis.read(buffer, 0, buffer.length)) > 0) {
lob.write(buffer, 0, s);
}
lob.close();
fis.close();
PreparedStatement ps = conn.prepareStatement("insert into test(id, name, content) values (nextval('test_id_seq'), ?, ?)");
ps.setString(1, "foto01");
ps.setLong(2, oid);
ps.executeUpdate();
ps.close();
conn.commit();
}
Reading large object from database:
public static void main(String[] args) throws SQLException, FileNotFoundException, IOException {
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/test01", "postgres", "postgres");
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select id, name, content from test");
LargeObjectManager lom = PGConnection.class.cast(conn).getLargeObjectAPI();
byte[] buffer = new byte[2048];
int s = 0;
while(rs.next()) {
File file = new File("/tmp", rs.getLong("id") + "_" + rs.getString("name"));
FileOutputStream fos = new FileOutputStream(file);
LargeObject lob = lom.open(rs.getLong("content"), LargeObjectManager.READ);
while((s = lob.read(buffer, 0, buffer.length)) > 0) {
fos.write(buffer, 0, buffer.length);
}
lob.close();
fos.close();
}
conn.close();
}
Test table was defined as
create table test (id serial, name varchar(256), content oid);
来源:https://stackoverflow.com/questions/37092628/empty-file-after-download