1

我正在尝试将文件从 flash 小部件上传到我的 rails 应用程序,该应用程序使用 attachment_fu 来处理上传的图像。我使用 Flash 上传,因为它可以轻松选择和上传多个文件。save!但是,当 rails 控制器尝试调用新创建的 ActiveRecord 对象时,我收到此错误:

ActiveRecord::RecordInvalid (Validation failed: Content type is not included in the list):
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/validations.rb:946:in `save_without_transactions!'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:112:in `save!'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:66:in `transaction'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:80:in `transaction'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:100:in `transaction'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:112:in `save!'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:120:in `rollback_active_record_state!'
    /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:112:in `save!'
    /app/controllers/photos_controller.rb:13:in `create'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `send'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `perform_action_without_filters'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:697:in `call_filters'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:689:in `perform_action_without_benchmark'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'

因此,似乎没有正确发送内容类型。事实上,Flash 发送的内容类型是application/octet-stream,我希望它是image/png(对于这个特定的测试用例)。

我执行上传的 ActionScript 3.0 代码如下所示:

var request:URLRequest = new URLRequest(paramObj.serverUrl + "/albums/" + paramObj.albumId + "/photos");
var variables:URLVariables = new URLVariables();
variables["photo[title]"] = file.name;
variables["authenticity_token"] = paramObj.authenticity_token;
variables["commit"] = "Upload Photo";
request.data = variables;
request.method = URLRequestMethod.POST;
file.upload(request, 'photo[uploaded_data]');

表单参数都存在于您期望从常规浏览器上传中获得的 Flash 上传中。运行数据包嗅探器后,我能看到的唯一真正区别是内容类型不同。

该模型使用 attachment_fu,如下所示:

class Photo < ActiveRecord::Base
  belongs_to :album

  has_attachment :content_type => :image, 
                 :storage => :file_system, 
                 :max_size => 10.megabytes, 
                 :thumbnails => { 
                   :thumb  => '100x100>',  
                   :large  => '800x600>', 
                 } 

  validates_as_attachment
end

那么,如何修复 flash 发送的内容类型呢?而且,为什么 attachment_fu 信任浏览器发送的内容类型,而不是使用幻数或其他东西自行确定?

我注意到,如果我删除:content_type => :imagevalidates_as_attachment,或者如果我将控制器更改为 call save(false),则会创建对象,但 attachment_fu 不会完成调整图像大小的工作。

4

1 回答 1

5

不幸的是,Flash 上传总是以内容类型“application/octet-stream”发送。可能最简单的解决方法是使用mimetype_fu在 before_validation 回调中猜测 mimetype。 Paperclip内置了此功能。

另一种选择是覆盖 is_image? 使用您的图像处理器来实际确定文件是否是图像(例如,在 rmagick 中,您可以打开它并查看它是否有任何图层)。这绝对是一个资源密集型解决方案,但它确保您接受所有可以处理的文件,而不是其他文件。

于 2009-05-08T15:25:23.707 回答