Ruby 在数据库中上载图像

Ruby 在数据库中上载图像,ruby,ruby-on-rails-3,postgresql,ruby-on-rails-3.1,Ruby,Ruby On Rails 3,Postgresql,Ruby On Rails 3.1,我想将上传的图像保存在PostgreSQL数据库的bytea列中。我正在寻找关于如何将Rails中的图像保存到bytea列中的建议,最好有示例 我使用Rails 3.1和“pg”驱动程序连接到PostgreSQL 将图像单独存储在数据库中通常不是一个好主意 请参阅和上的讨论。请注意,这些问题及其答案并不是专门针对PostgreSQL的 这方面有一些PostgreSQL特有的缺陷。PostgreSQL没有任何用于增量转储的功能*,因此如果使用pg_dump备份,则每次备份都必须转储所有图像数据。存

我想将上传的图像保存在PostgreSQL数据库的
bytea
列中。我正在寻找关于如何将Rails中的图像保存到
bytea
列中的建议,最好有示例

我使用Rails 3.1和“pg”驱动程序连接到PostgreSQL

将图像单独存储在数据库中通常不是一个好主意 请参阅和上的讨论。请注意,这些问题及其答案并不是专门针对PostgreSQL的

这方面有一些PostgreSQL特有的缺陷。PostgreSQL没有任何用于增量转储的功能*,因此如果使用
pg_dump
备份,则每次备份都必须转储所有图像数据。存储空间和传输时间可能是一个问题,特别是因为您应该保存数周的备份,而不仅仅是一次最新的备份

如果图像很大或很多,则可能需要考虑将图像存储在文件系统中,除非您对事务性的、符合ACID的访问有很强的需求。将文件名存储在数据库中,或者根据有用的密钥建立文件命名约定。这样,您就可以轻松地对映像目录进行增量备份,并将其单独管理到数据库中

如果将图像存储在FS中,则无法通过PostgreSQL数据库连接轻松†访问它们。因此,您可以通过HTTP直接从文件系统为它们提供服务,这比您必须首先从数据库查询它们时所希望的效率要高得多。特别是,如果您的图像位于FS上,但不是来自数据库,则可以使用

如果您真的必须将图像存储在数据库中 。。。然后它在概念上与.NET中相同,但具体细节取决于您使用的Pg驱动程序,您没有指定

有两种方法可以做到这一点:

  • 按照您的要求,通过TEA存储和检索
    ;及
  • 使用内置的大对象支持,这通常比使用
    bytea
    更可取
对于bytea正常的小图像:
  • 从客户端将图像数据读入局部变量
  • 通过将变量作为bytea传递,将其插入数据库。假设您使用的是
    ruby pg
    驱动程序,该驱动程序中的示例应该会对您有所帮助
对于较大的图像(超过几兆字节),请使用
lo
: 对于较大的图像,请不要使用
bytea
。理论上最大值可能是2GB,但是您应该避免对大型图像或其他大型二进制数据使用
bytea

PostgreSQL对此有自己的优势。关于9.1,仅:

CREATE EXTENSION lo;
CREATE TABLE some_images(id serial primary key, lo image_data not null);
。。。然后使用从磁盘上的临时文件中读取数据,这样就不必一次将整个内容放入RAM中

驱动程序
ruby pg
提供了
lou-create
lou-open
等功能,并为本地文件访问提供了
lou-import
。看

请使用大型对象,而不是
bytea


*通过流式复制、PITR/WAL归档等,增量备份是可能的,但再次增加数据库大小会使WAL管理等工作变得复杂。无论如何,除非你是专家(或“勇敢者”),否则你应该进行
pg_dump
备份,而不是仅仅依靠回复和PITR。通过增加数据库的大小,将映像放入数据库也将大大降低
pg_basebackup
,这在故障切换场景中可能很重要


†通过Pg连接为超级用户提供本地文件访问。不过,您的webapp用户永远不应该拥有超级用户权限,甚至不应该拥有它所使用的表的所有权。您的文件是否通过单独的安全通道(如
WebDAV

读取和写入请显示您为解决问题而编写的代码。现在我只需将文件加载到文件夹中,但需要将其保存在数据库中。我只编写过ASP.NET,现在正在学习ruby。我知道如何在.NET中实现这一点,我需要一个Rails上的示例。@user1466717您正在使用哪个用于Ruby的PostgreSQL驱动程序?我使用gem pg@user1466717,然后看到如下想法。我的文件将存储在数据库和文件系统中。如果文件从文件系统中删除,它将再次从数据库文件中自动加载并存储在文件夹中。@user1466717 Urk,为什么?这是两个世界中最糟糕的。你想用这种方法解决什么问题?根本的问题是什么,您想这样做的原因是什么?@user1466717 BTW,答案更新为for
bytea
access的链接。当您查看页面时,图像将从文件系统发出。如果传输或意外删除文件,则第一页加载是从基本图片中从头开始加载和配置的。这将保存所有图像,并且不会在每次加载页面时加载数据库。@jug,它引用数据库中的大型对象。
lo
伪类型为您解决了这一问题,无需自定义编码,因此它比手动滚动触发器更安全。对于管理外部文件,您可以
NOTIFY
a
LISTEN
ing进程来告诉它删除文件;理想情况下,数据库的文件系统访问权限不应超过其绝对需要的权限,因此不应自行删除它们。