【问题标题】:Insert InputStream into PostgreSQL将 InputStream 插入 PostgreSQL
【发布时间】:2016-08-29 11:51:48
【问题描述】:

我想实现文件上传到 PostgreSQL。我试过这个解决方案:

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

但我收到此错误:

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 postgresql jdbc postgresql-9.3 postgresql-9.2


【解决方案1】:

在持久化之前,您必须将 InputStream 转换为 Oid 对象。为此,只需创建一个新的 Oid 并传递您从 IS 获得的字节数组:

 Oid oid = new Oid(IOUtils.readFully(inputStream, -1, false));

然后您将在准备好的语句中传递 oid。

数据库方面的另一种解决方案是将表的列更改为 BLOB 类型。

【讨论】:

  • 可能你的意思是我需要投射inputStream
  • 一个一般性问题。如果我在具有 1 GB RAM 的服务器上上传 2 GB 文件会发生什么?
  • 您将收到 OutOfMemoryError。不过,InputStream 也会发生同样的情况。
  • 有什么解决办法吗?一般来说,解决方案可能是在服务器上配置 10 GB SWAP 内存,或者我可以先在 tmp firecotry 上上传文件,然后在 PostgreSQL 中上传?
  • 解决方案将取决于您的需求。您可以按照您所说的交换内存,或者如果您正在开发一个将有不同用户的应用程序,您可以检查文件大小并在文件太大时返回错误。
猜你喜欢
  • 2019-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 2012-04-25
  • 2021-03-10
  • 1970-01-01
相关资源
最近更新 更多