Я разрабатываю приложение Sinatra, состоящее из формы загрузки, с индикатором выполнения, показывающим, сколько загрузки было завершено. Процесс, описанный ryan dahl, выглядит следующим образом:
Графики выполнения HTTP-загрузки довольно запутаны - они обычно включают процесс, выполняющийся на сервере, отслеживающий размер временного файла, который пишет HTTP-сервер, а затем на стороне клиента вызов AJAX выполняется каждые пару секунд до сервер во время загрузки, чтобы запросить ход загрузки.
Каждая загрузка имеет случайный session-id, и для отслеживания связи я использую class variable в своем приложении (я знаю, это ужасно - если у вас есть лучшие идеи, скажите, пожалуйста)
configure do
@@assoc = {}
end
У меня есть маршрут POST для загрузки и GET один для опроса AJAX.
Внутри маршрута POST я сохраняю ассоциацию session-id, Tempfile и общий размер.
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, что на самом деле не имеет смысла, ve только присвоил @@assoc[@sid] значение в другом маршруте.
Итак, что мне здесь не хватает?
EDIT: Я пробовал
-
set :reload, false -
set :environment, :production -
config { @@assoc ||= {} } - Я также пытался бросить реляционный db на нем (SQLite с DataMapper)
Ни работали.