One of my recent projects required the use of SWFUpload on a Rails 2.1 project. The project involved users uploading multiple photographs, and each photographs must be associated with an authenticated user. The problem is that SWFUpload doesn’t play nice with Rails 2 when it comes to handling sessions.
Here are some of the issues:
One way around this is to monkey-patch CGI::Session so it forcibly sets session_id from the query string.
These solutions are outdated. Rails 2.1 will detect the presence of the :session_key set in config/environment.rb and throw an error. The solution is a kludge on top of a kludge:
# Add this to config/initaializers/swfupload_session_hack.rb
# Based on the code from http://seventytwo.co.uk/posts/making-swfupload-and-rails-work-together
# The following code is a work-around for the Flash 8 bug that prevents our multiple file uploader
# from sending the _session_id. Here, we hack the Session#initialize method and force the session_id
# to load from the query string via the request uri. (Tested on Lighttpd, Mongrel, Apache)
class CGI::Session
alias original_initialize initialize
def initialize(request, option = {})
option = scan_for_session_id(request, '_swfupload_session_id', option) unless option['session_id']
original_initialize(request, option)
end
def scan_for_session_id(request, session_key = '_session_id', option = {})
query_string = if (qs = request.env_table["QUERY_STRING"]) and qs != ""
qs
elsif (ru = request.env_table["REQUEST_URI"][0..-1]).include?("?")
ru[(ru.index("?") + 1)..-1]
end
if query_string and query_string.include?(session_key)
option['session_id'] = query_string.scan(/#{session_key}=(.*?)(&.*?)*$/).flatten.first
end
return option
end
end
Then in the upload view, you have to use:
upload_url: "<%= photographs_path %>?_swfupload_session_id=<%=h session.session_id %>"
Note that you are passing the session key to _swfupload_session_id, and not whatever session key is set in config/environment.rb.
I have tried this with Cookie Store, and it fails to work, at least on Firefox 3. The reason is that session.session_id will return the entire encoded session, including newlines that messes up the Javascript. There are probably ways around this, but considering that I wasn’t going to use Cookie Store when it goes into production, I switched it using to ActiveStore. This is likely to work with memcached session store, but I have not tested that yet.
Sorry, comments are closed for this article.
October 21st, 2008 at 10:07 AM I'm using ActiveStore also but I got error about authenticity token. Testing in Leopard, Mongrel, Rails 2.1 and FireFox 3 ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): /Library/Ruby/Gems/1.8/gems/actionpack-2.1.1/lib/action_controller/request_forgery_protection.rb:86:in `verify_authenticity_token'