Почему не работает загрузка из Flash в Rails & attachment_fu (это связано с типом контента)? - PullRequest
1 голос
/ 08 мая 2009

Я пытаюсь загрузить файл из флэш-виджета в мое приложение rails, которое использует attachment_fu для обработки загруженных изображений. Я использую Flash для загрузки, так как он позволяет легко выбирать и загружать несколько файлов. Однако я получаю эту ошибку, когда контроллер rails пытается вызвать save! для вновь созданного объекта 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

Итак, как я могу исправить тип контента, который отправляет флэш? И почему attachment_fu доверяет типу контента, отправляемому браузером, а не определяет его самостоятельно, используя магические числа или что-то еще?

Я заметил, что если я удаляю :content_type => :image или validates_as_attachment, или если я изменяю контроллер на вызов save(false), объект создается, но attachment_fu не выполняет свою работу по изменению размера изображения.

1 Ответ

5 голосов
/ 08 мая 2009

К сожалению, Flash-загрузки всегда отправляются с типом контента «application / octet-stream». Вероятно, самый простой обходной путь - использовать mimetype_fu , чтобы угадать mimetype в обратном вызове before_validation. Скрепка имеет эту встроенную функцию.

Другой вариант - перезаписать is_image? использовать ваш процессор изображений, чтобы фактически определить, является ли файл изображением (например, в rmagick вы можете открыть его и посмотреть, есть ли в нем какие-либо слои). Это определенно более ресурсоемкое решение, но оно гарантирует, что вы принимаете все файлы, которые можете обрабатывать, а не другие.

...