我正在尝试使用JSF 2.3实现文件上传:
@Inject
@Push
private PushContext uploadProgress;
private static final Logger logger = Logger.getLogger(NewProcedure.class.getName());
private Part file;
public Part getFile()
{
return file;
}
public void setFile(Part file)
{
this.file = file;
}
public void upload() throws SQLException
{
if (file != null)
{
try (InputStream inputStream = file.getInputStream();
//FileOutputStream outputStream = new FileOutputStream(path)
)
{
long lastTimestamp = System.currentTimeMillis();
int pushInterval = 1000;
long totalRead = 0;
long size = file.getSize();
int bytesRead = 0;
final byte[] chunck = new byte[1024];
while ((bytesRead = inputStream.read(chunck)) != -1)
{
// outputStream.write(chunck, 0, bytesRead);
totalRead += bytesRead;
if (System.currentTimeMillis() > lastTimestamp + pushInterval)
{
lastTimestamp = System.currentTimeMillis();
uploadProgress.send(100.0 * totalRead / size); // Make sure this isn't sent more often than once per second.
}
}
Connection conn = ds.getConnection();
// insert into database file
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, "tests");
ps.setBinaryStream(4, inputStream);
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();
}
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Upload successfully ended!"));
}
catch (IOException e)
{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Upload failed!"));
}
}
}
我想将文件直接插入数据库,但出现错误:
org.postgresql.util.PSQLException: ERROR: column "file" is of type oid but expression is of type bytea
Hint: You will need to rewrite or cast the expression.
将文件插入数据库的正确方法是什么?
可能我需要使用其他Java对象来存储文件?
PS我尝试了这个:
public static byte[] getBytesFromInputStream(InputStream is) throws IOException
{
try (ByteArrayOutputStream os = new ByteArrayOutputStream();)
{
byte[] buffer = new byte[0xFFFF];
for (int len; (len = is.read(buffer)) != -1;)
os.write(buffer, 0, len);
os.flush();
return os.toByteArray();
}
}
public void upload() throws SQLException
{
if (file != null)
{
try
{
InputStream inputStream = file.getInputStream();
byte[] bytesFromInputStream = getBytesFromInputStream(inputStream);
ByteArrayInputStream input = new ByteArrayInputStream(bytesFromInputStream);
long lastTimestamp = System.currentTimeMillis();
int pushInterval = 1000;
long totalRead = 0;
long size = file.getSize();
int bytesRead = 0;
final byte[] chunck = new byte[1024];
while ((bytesRead = inputStream.read(chunck)) != -1)
{
// outputStream.write(chunck, 0, bytesRead);
totalRead += bytesRead;
if (System.currentTimeMillis() > lastTimestamp + pushInterval)
{
lastTimestamp = System.currentTimeMillis();
uploadProgress.send(100.0 * totalRead / size); // Make sure this isn't sent more often than once per second.
}
}
Connection conn = ds.getConnection();
// insert into database file
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.setBinaryStream(4, input, input.available());
ps.executeUpdate();
ps.close();
conn.commit();
committed = true;
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{}
}
catch (IOException e)
{}
}
}
最佳答案
删除while循环读取inputStream。
通过设置列file
的二进制输入流来进行读取。
这需要另一种进度指示。
现在发生的事情是inputStream被读取到末尾,并且准备好的语句只能读取0个字节。
public void upload() throws SQLException {
if (file != null) {
try (InputStream inputStream = file.getInputStream()) {
long lastTimestamp = System.currentTimeMillis();
int pushInterval = 1000;
long totalRead = 0;
long size = file.getSize();
Connection conn = ds.getConnection();
// insert into database file
boolean committed = false;
try {
conn.setAutoCommit(false);
try (PreparedStatement 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, "tests");
ps.setBinaryStream(4, inputStream);
ps.executeUpdate();
}
conn.commit();
committed = true;
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
if (!committed) {
conn.rollback();
}
conn.close();
}
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Upload successfully ended!"));
}
catch (IOException e) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Upload failed!"));
}
}
}
关于java - "file"列的类型为oid,但表达式的类型为byte,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37012660/