Чтобы контроллер смог одновременно принимать файл из формы и файлы из флеша, делаем следующее:
controllers/photos_controller.rb:
def createопуская обычную форму, привожу флешевую
if params[:Filedata]
@photo = Photo.new(:swfupload_file => params[:Filedata])
if @photo.save
render :text => 'photo'
else
render :text => "error"
end
else
photo = Photo.create(params[:photo])
redirect_to photos_path, :notice => "Фотография добавлена"
end
end
views/images/form.haml:
%div{:class => "fieldset flash", :id => "fsUploadProgress"}этот кусок инлайн-js я выделил для удобства в отдельный файл
%span.legend Очередь загрузки
%div#Status 0 файлов загружено
%div
%table
%tr
%td
%span#spanButtonPlaceHolder Не работает, что-то не так с яваскриптом или флешем :(
%td
%input#btnCancel{:type => "button", :value => "Отменить все загрузки", :onclick => "swfu.cancelQueue();", :disabled => "disabled", :style => "margin-left: 2px; font-size: 8pt; height: 29px;"}
=render 'swfu'
_swfu.erb:
<script src="/swfu/swfupload.js" type="text/javascript"></script>Как тут можно увидеть, флеш отсылает параметры для того, чтоб было понятно, что это за юзер шлет нам файло. Было настоящей головной болью заставить флеш авторизоваться в Rails приложении именно на стороне сервера, потому как ну не происходит магии превращения переменных в полноценную сессию. Как выход из ситуации создаем
<script src="/swfu/swfupload.queue.js" type="text/javascript"></script>
<script src="/swfu/fileprogress.js" type="text/javascript"></script>
<script src="/swfu/handlers.js" type="text/javascript"></script>
<link href="/swfu/swfupload.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var swfu;
window.onload = function() {
var settings = {
flash_url : "/swfu/swfupload.swf",
upload_url: "<%= photos_path %>",
post_params: {
"<%= key = Rails.application.config.session_options[:key] %>" : "<%= cookies[key] %>",
"<%= request_forgery_protection_token %>" : "<%= form_authenticity_token %>"
},
file_size_limit : "100 MB",
file_types : "*.*",
file_types_description : "All Files",
file_upload_limit : 100,
file_queue_limit : 0,
custom_settings : {
progressTarget : "fsUploadProgress",
cancelButtonId : "btnCancel"
},
debug: false,
// Button settings
button_image_url: "/swfu/TestImageNoText_65x29.png",
button_width: "65",
button_height: "29",
button_placeholder_id: "spanButtonPlaceHolder",
button_text: '<span>Загрузить</span>',
button_text_style: ".theFont { font-size: 16; }",
button_text_left_padding: 8,
button_text_top_padding: 3,
// The event handler functions are defined in handlers.js
file_queued_handler : fileQueued,
file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,
upload_start_handler : uploadStart,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
upload_complete_handler : uploadComplete,
queue_complete_handler : queueComplete // Queue plugin event
};
swfu = new SWFUpload(settings);
};
</script>
app/middleware/flash_session_cookie_middleware.rb
В config/application.rb надо добавить в автозагрузку путь "app/middleware".require 'rack/utils'class FlashSessionCookieMiddleware
def initialize(app, session_key = '_session_id')
@app = app
@session_key = session_key
enddef call(env)
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
req = Rack::Request.new(env)
env['HTTP_COOKIE'] = [ @session_key, req.params[@session_key] ].join('=').freeze unless req.params[@session_key].nil?
env['HTTP_ACCEPT'] = "#{req.params['_http_accept']}".freeze unless req.params['_http_accept'].nil?
end
@app.call(env)
end
end
config/initializers/session_store.rb в конец:%w(observers mailers middleware).each do |dir|
config.autoload_paths << "#{config.root}/app/#{dir}"
end
Теперь файл нормально доходит до контроллера, но модель пока не знает, что такое swfupload_file=Rails.application.config.middleware.insert_before(
ActionDispatch::Session::CookieStore,
FlashSessionCookieMiddleware,
Rails.application.config.session_options[:key]
)
models/photo.rb
has_attached_file :image, :styles => {:thumbnail => '100x100#', :big => '800x600>'}Теперь всё должно работать. Единственное, где лично я споткнулся, это хранилище сессий, оно должно быть именно Cookies, или копайтесь дальше сами.
def swfupload_file=(data)
data.content_type = MIME::Types.type_for(data.original_filename).to_s
self.image = data
end
Комментариев нет:
Отправить комментарий