将大文件上传和下载到 PostgreSQL 而不消耗大量 RAM

Posted

技术标签:

【中文标题】将大文件上传和下载到 PostgreSQL 而不消耗大量 RAM【英文标题】:Upload and download big files into PostgreSQL without consuming a lot RAM 【发布时间】:2018-03-26 10:02:05 【问题描述】:

我设法使用此 Java 代码成功上传和下载文件:

上传

ps = conn.prepareStatement("INSERT INTO DOCUMENT_TEMPLATE_FILES (ID, DOCUMENT_TEMPLATE_ID, FILE_NAME, FILE) "
                    + " VALUES (?, ?, ?, ?)");
                ps.setInt(1, obj.number);
                ps.setInt(2, obj.number);
                ps.setString(3, file.getSubmittedFileName());

                InputStream inputStream = file.getInputStream();
                ps.setBinaryStream(4, inputStream, inputStream.available());

                ps.executeUpdate();

下载

ps = conn.prepareStatement("SELECT *, OCTET_LENGTH(FILE) AS FILE_LENGTH FROM DOCUMENT_TEMPLATE_FILES WHERE DOCUMENT_TEMPLATE_ID = ?");

            ps.setInt(1, id);
            ResultSet rs = ps.executeQuery();
            while (rs.next())
            
                String file_name = rs.getString("FILE_NAME");
                .........

                byte[] buffer = new byte[4096];

                try (InputStream input = rs.getBinaryStream("FILE");
                    OutputStream output = response.getOutputStream())
                
                    int numRead = 0;

                    while ((numRead = input.read(buffer)) != -1)
                    
                        output.write(buffer, 0, numRead);
                    
                

但是当我尝试将它用于 2GB 文件时,我得到了内存大小的异常。不幸的是,文件在插入/选择期间存储在 RAM 中。

是否有另一种方法可以在不消耗太多 RAM 内存的情况下解决此问题?

【问题讨论】:

file列的数据类型是什么? @a_horse_with_no_name 目前是 BYTEA,但如果您推荐,我可以更改它。 bytea 列的最大长度为 1GB @a_horse_with_no_name 好的,您可以推荐哪种列类型来解决上述问题? 您必须使用large objects,但使用起来相当复杂:jdbc.postgresql.org/documentation/head/binary-data.html 【参考方案1】:

为什么不使用本地文件系统来存储可以流式传输的文件,而只使用数据库中的文件信息?数据库中的 2GB 文件是一个坏主意,那么您试图通过膨胀表空间来实现什么?只需选择文件名并启动 Streamreader/Streamwriter。

【讨论】:

这将需要 Java 程序在数据库服务器上运行——这通常不是这种情况 是的,关于数据库服务器上的 Java 程序,您是对的。但这就是发明cdn服务器的原因,只需返回链接并将http 301返回到cdn链接。只是一个想法,将这么大的 blob 存储到数据库是不常见的,单独备份它有时会很糟糕。

以上是关于将大文件上传和下载到 PostgreSQL 而不消耗大量 RAM的主要内容,如果未能解决你的问题,请参考以下文章

C#如何将大文件上传到ftp站点

将大文件上传到 Apache FileUpload 时忽略 Servlet 响应

如何将大文件上传到 Azure Blob 存储 (.NET Core)

无法将大文件上传到 Google 文档

将大文件上传到 sitecore 媒体库

支持恢复将大文件上传到 S3