列“file”的类型为oid,但表达式的类型为byte

时间:2016-05-03 19:21:25

标签: java sql postgresql-9.3 postgresql-9.2

我正在尝试使用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 Object来存储文件吗?

P.S我试过这个:

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)
            {}
        }
    }

1 个答案:

答案 0 :(得分:1)

删除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!"));
        }
    }
}