10

我正在开发一个 Sinatra 应用程序,它包含一个上传表单,进度条指示上传完成了多少。如ryan dahl所述,该过程如下:

HTTP 上传进度条相当模糊 - 它们通常涉及在服务器上运行的进程,跟踪 HTTP 服务器正在写入的临时文件的大小,然后在客户端每隔几秒钟对服务器进行一次 AJAX 调用。上传以询问上传进度。

每个上传都有一个随机的session-id,并且为了跟踪我class variable在我的应用程序中使用的关联(我知道,这太可怕了——如果你有更好的想法,请告诉我)

configure do
  @@assoc = {}
end

我有一条POST上传路线和GET一条用于 AJAX 轮询的路线。在POST路线内,我保存了session-idTempfile和 总大小的关联。

post '/files' do
  tmp = params[:file][:tempfile]
  # from here on, @@assoc[@sid] should have a value, even in other routes
  @@assoc[@sid] = { :file => tmp, :size => env['CONTENT_LENGTH'] } 
  File.open("#{options.filesdir}/#{filename}", 'w+') do |file|
    file << tmp.read
  end
end 

GET路线中,我根据Tempfile的当前大小计算百分比:

get '/status/:sid' do
  h = @@assoc[params[:sid]]
  unless h.nil?
    percentage = (h[:file].size / h[:size].to_f) * 100 
    "#{percentage}%"
  else
    "0%"
  end 
end

问题是,直到POST请求尚未完成(即,在它读取了所有的 之后Tempfile)才h.nil?返回true,这实际上没有意义,因为我刚刚@@assoc[@sid]在另一条路线中分配了一个值。

那么,我在这里缺少什么?

编辑:我试过

  • set :reload, false
  • set :environment, :production
  • config { @@assoc ||= {} }
  • 我还尝试向它扔一个关系数据库(带有 DataMapper 的 SQLite)

都没有奏效。

4

2 回答 2

4

我想我明白了问题所在:

tmp = params[:file][:tempfile]在文件完全接收之前不会返回。

于 2010-06-22T22:50:08.623 回答
1
@@assoc[@sid] = { :file => tmp, :size => env['CONTENT_LENGTH'] }

应该

@@assoc[params[:sid]] = { :file => tmp, :size => env['CONTENT_LENGTH'] }
于 2010-06-22T18:37:17.303 回答