Rails Binary Stream支持

时间:2020-03-05 18:51:39  来源:igfitidea点击:

我即将开始一个需要支持大型二进制文件的项目。我想在Webapp上使用Ruby on Rails,但是我对BLOB的支持感到担忧。根据我在其他语言,框架和数据库中的经验,BLOB通常被忽略,因此功能差,困难和/或者错误。

RoR是否充分分配BLOB?一旦我们已经致力于Rails,是否会有任何陷阱?

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

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

解决方案

回答

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

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

回答

我们可以在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 String。

回答

+1(对于attach_fu)

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

处理w / BLOB的(一个?)棘手的事情是,我们需要一个单独的代码路径来将数据发送给用户-我们不能像在文件系统中那样简单地内联路径纯简文件。

例如如果我们要存储头像信息,则不能简单地执行以下操作:

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

我们必须编写一些包装器逻辑并使用send_data,例如(下面仅是一个带有附件的示例,实际上,我们需要对此进行干燥)

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

不幸的是,据我所知,attachment_fu(我没有最新版本)不能为我们提供巧妙的包装-我们必须自己编写。

P.S.
看到问题编辑后,Attachment_fu处理了我们提到的所有烦人的事情-关于需要知道文件路径和所有废话的内容-除了存储在数据库中的一个小问题。试试看;这是Rails应用程序的标准。如果我们坚持要重新发明轮子,那么attachment_fu的源代码也应该记录大多数陷阱!

回答

看看插件x_send_file。

" XSendFile插件提供了一个简单的界面,用于通过X-Sendfile HTTP标头发送文件。这使Web服务器可以直接从磁盘提供文件,而不是通过Rails流程对其进行流传输。这更快并且节省了大量内存如果我们使用的是Mongrel,则并非每个Web服务器都支持此标头。

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

回答

对于流媒体,我们可以(至少在内存方面)高效的方式完成所有操作。在上传方面,表格中的文件参数被抽象为我们可以读取的IO对象。在下载端,查看带有Proc参数的render:text =>形式:

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

但是,如果东西在磁盘上的文件中,则上述解决方案肯定会更好地工作。