写流到回形针

时间:2011-03-02 11:24:26

标签: ruby-on-rails stream paperclip

我想存储收到的电子邮件附件以及回形针的使用情况。从电子邮件我得到part.body,我不知道如何把它放到回形针模型。现在我创建临时文件并将port.body写入其中,将此文件存储到paperclip,然后删除文件。以下是我使用临时文件的方法:

    l_file = File.open(l_path, "w+b", 0644)
    l_file.write(part.body)
    oAsset = Asset.new(
        :email_id => email.id, 
        :asset => l_file, 
        :header => h, 
        :original_file_name => o, 
        :hash => h)
    oAsset.save
    l_file.close
    File.delete(l_path)

:asset是我的'has_attached_file'字段。有没有办法省略文件创建并执行以下操作::asset => part.body in Asset.new?

7 个答案:

答案 0 :(得分:21)

假设您使用mail gem阅读电子邮件,我会这样做。你需要整个电子邮件'part',而不仅仅是part.body

file = StringIO.new(part.body) #mimic a real upload file
  file.class.class_eval { attr_accessor :original_filename, :content_type } #add attr's that paperclip needs
  file.original_filename = part.filename #assign filename in way that paperclip likes
  file.content_type = part.mime_type # you could set this manually aswell if needed e.g 'application/pdf'

现在只需使用文件对象保存到Paperclip关联。

a = Asset.new 
a.asset = file
a.save!

希望这有帮助。

答案 1 :(得分:9)

Barlow的答案很好,但它实际上是对StringIO类进行猴子修补。在我的情况下,我正在使用Mechanize :: Download#body_io,我不想污染这个类导致在应用程序中突然出现的意外错误。所以我在实例元类上定义方法如下:

original_filename = "whatever.pdf" # Set local variables for the closure below
content_type = "application/pdf"

file = StringIO.new(part.body)

metaclass = class << file; self; end
metaclass.class_eval do
  define_method(:original_filename) { original_filename }
  define_method(:content_type) { content_type }
end

答案 2 :(得分:6)

我喜欢gtd的答案,但它可以更简单。

file = StringIO.new(part.body)

class << file
  define_method(:original_filename) { "whatever.pdf" }
  define_method(:content_type) { "application/pdf" }
end

并不需要提取&#34;元类&#34;进入局部变量,只需将一些类附加到对象。

答案 3 :(得分:2)

从ruby 1.9开始,您可以使用StringIO和define_singleton_method:

def attachment_from_string(string, original_filename, content_type)
  StringIO.new(string).tap do |file|
    file.define_singleton_method(:original_filename) { original_filename }
    file.define_singleton_method(:content_type) { content_type }
  end
end

答案 4 :(得分:0)

作为对David-Barlow的回答的评论本来会更好,但是我还没有足够的声望点...

但是,正如其他人提到的那样,我不喜欢猴子打补丁。相反,我只是创建了一个从StringIO继承的新类,如下所示:

class TempFile < StringIO
  attr_accessor :original_filename, :content_type  
end

答案 5 :(得分:0)

为了后代,这是最好的答案。将顶部放在 vendor/paperclip/data_uri_adapter.rb 中,将底部放在 config/initializers/paperclip.rb 中。

https://github.com/thoughtbot/paperclip/blob/43eb9a36deb09ce5655028a1061578dbf0268a5d/lib/paperclip/io_adapters/data_uri_adapter.rb

这需要一个数据 URI 方案流,但现在这似乎很常见。只需将您的回形针变量设置为包含流数据的字符串,其余的由代码处理。

答案 6 :(得分:-1)

我使用类似的技术将图像下拉到回形针

这应该可行,但是未经测试:

io = part.body
def io.original_filename; part.original_file_name || 'unknown-file-name'; end

asset = Asset.new(:email=>email)
asset.asset = io

当我们将IO直接分配给回形针实例时,它需要有一个.original_file_name,这就是我们在第二行中所做的。