Rails 二进制流支持

Posted

技术标签:

【中文标题】Rails 二进制流支持【英文标题】:Rails Binary Stream support 【发布时间】:2010-09-08 14:20:38 【问题描述】:

我将很快开始一个需要支持大型二进制文件的项目。我想为 webapp 使用 Ruby on Rails,但我担心 BLOB 支持。根据我使用其他语言、框架和数据库的经验,BLOB 经常被忽视,因此功能很差、困难和/或有问题。

RoR 是否充分支持 BLOB?一旦你已经致力于 Rails,有没有什么陷阱?

顺便说一句:我想使用 PostgreSQL 和/或 mysql 作为后端数据库。显然,底层数据库中的 BLOB 支持很重要。目前,我想避免关注数据库的 BLOB 功能;我对 Rails 本身的反应更感兴趣。理想情况下,Rails 应该对我隐藏数据库的详细信息,因此我应该能够从一个切换到另一个。如果不是这种情况(即:使用带有特定数据库的 Rails 存在一些问题),请务必提及。

更新:另外,我在这里谈论的不仅仅是 ActiveRecord。我需要在 HTTP 端处理二进制文件(文件上传有效)。这意味着通过 Rails 访问适当的 HTTP 标头和流。我已更新问题标题和说明以反映这一点。

【问题讨论】:

【参考方案1】:

我认为你最好的选择是 attachment_fu 插件: http://github.com/technoweenie/attachment_fu/tree/master

更新:在这里找到更多信息http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/a81beffb93708bb3

【讨论】:

【参考方案2】:

您可以在 ActiveRecord 迁移中使用 :binary 类型并限制最大大小:

class BlobTest < ActiveRecord::Migration
  def self.up
    create_table :files do |t|
      t.column :file_data, :binary, :limit => 1.megabyte
    end
  end
end

ActiveRecord 将 BLOB(或 CLOB)内容公开为 Ruby 字符串。

【讨论】:

【参考方案3】:

attachment_fu +1

我在我的一个应用程序中使用 attachment_fu 并且必须将文件存储在数据库中(出于烦人的原因,这超出了此 convo 的范围)。

我发现处理 BLOB 的(一个?)棘手的事情是你需要一个单独的代码路径来将数据发送给用户——你不能像你一样简单地在文件系统上内联路径如果它是一个普通的简文件。

例如如果您要存储头像信息,则不能简单地这样做:

<%= image_tag @youruser.avatar.path %>

您必须编写一些包装逻辑并使用 send_data,例如(以下只是一个带有attachment_fu 的示例,实际上您需要将其干燥)

send_data(@youruser.avatar.current_data, :type => @youruser.avatar.content_type, :filename => @youruser.avatar.filename, :disposition => 'inline' )

不幸的是,据我所知,attachment_fu(我没有最新版本)并没有为你做巧妙的包装——你必须自己写。

附: 看到你的问题编辑 - Attachment_fu 处理你提到的所有烦人的东西 - 关于需要知道文件路径和所有这些废话 - 除了存储在数据库中时的一个小问题。试一试;它是 Rails 应用程序的标准。如果您坚持重新发明***,attachment_fu 的源代码也应该记录大部分问题!

【讨论】:

【参考方案4】:

查看插件,x_send_file。

“XSendFile 插件提供了一个简单的接口,用于通过 X-Sendfile HTTP 标头发送文件。这使您的 Web 服务器能够直接从磁盘提供文件,而不是通过 Rails 进程流式传输文件。这样更快并节省了如果您使用 Mongrel,则需要大量内存。并非每个 Web 服务器都支持此标头。YMMV。"

我不确定它是否可用于 Blob,它可能仅适用于文件系统上的文件。但是您可能需要一些不会占用 Web 服务器流式传输大量数据的东西。

【讨论】:

【参考方案5】:

至于流式传输,您可以以一种(至少是内存)高效的方式来完成这一切。在上传方面,表单中的文件参数被抽象为可以读取的 IO 对象;在下载端,查看带有 Proc 参数的render :text =&gt; 形式:

render :content_type => 'application/octet-stream', :text => Proc.new 
    |response, output|
    # do something that reads data and writes it to output

不过,如果您的资料在磁盘上的文件中,上述解决方案肯定会更好。

【讨论】:

Rails 现在有send_data。

以上是关于Rails 二进制流支持的主要内容,如果未能解决你的问题,请参考以下文章

字节流和字符流的比较。

Netty4.0学习笔记系列之六:多种通讯协议支持

Qt文本流和数据流

Java输入输出流总结(转载)

接口返回文件流,如何下载

C++流 文件流 二进制文件流读写