Rails 使用 Swfupload 无刷新多文件上传的 Session 问题解决
Swfupload 是一个 Javascript + Flash 实现的无刷新上传组件,它支持一次选择多个文件上传、上传状态、进度等实用功能。
在 Ruby on Rails 里面使用 Swfupload 来实现多文件上传基本上很简单,按照 Demo 这个页面的例子代码,并修改制定的参数就好了。
但是,如果你的上传需要验证用户登录,那就会有问题出现了。
因为 Swfupload 上传是在 Flash 里面实现的,也就是说 Swfupload 和页面的 Cookie 将会是两个,Session 当然也是同样的。
要避免这个问题,就需要强制的改写 Cookie。
步骤
- 在 Rails 项目里面创建
app/middlewares
目录
- 创建
app/middlewares/flash_session_cookie_middleware.rb
文件,并存入这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| require 'rack/utils'
class FlashSessionCookieMiddleware
def initialize(app, session_key = '_session_id')
@app = app
@session_key = session_key
end
def call(env)
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
env['HTTP_COOKIE'] = [ @session_key, params[@session_key] ].join('=').freeze unless params[@session_key].nil?
end
@app.call(env)
end
end
|
- 修改
config/initializers/session_store.rb
并加入:
1
2
3
| # config/initializers/session_store.rb
ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store,
FlashSessionCookieMiddleware, ActionController::Base.session_options[:key])
|
- 修改
config/environment.rb
将 app/middlewares
目录加入到 config.load_paths
里面:
1
2
3
4
5
6
| # config/environment.rb
Rails::Initializer.run do |config|
# ..... 省略其他的一些代码
config.load_paths += %W( #{RAILS_ROOT}/app/middlewares )
# ..... 省略其他的一些代码
end
|
- 对 脚本的 upload_url 进行修改,加入 session 参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| <!-- 如原始的代码是这样 -->
<script type="text/javascript">
var swfu;
window.onload = function () {
swfu = new SWFUpload({
upload_url: '<%= link_to :controller => "photos", :action => "create" %>',
//....... 省略后面的...
}
</script>
<!-- 修改为 -->
<script type="text/javascript">
var swfu;
window.onload = function () {
swfu = new SWFUpload({
upload_url: '<%= link_to :controller => "photos", :action => "create", ActionController::Base.session_options[:key]
=> cookies[ActionController::Base.session_options[:key]] %>',
//....... 省略后面的...
}
</script>
<!--
这样一来,upload_url 就会从之前的
/photos/create
变为
/photos/create?_projectname_session_key=asdgkljasdklgjasdklgjlakjlwje
类似的地址
_projectname_session_key 是在 config/initializers/session_store.rb 里面配置的
ActionController::Base.session 的 :key 的值
-->
|
1
| session :cookie_only => false, :only => :create
|
参考资料: