Я разрабатываю приложение 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)
Ни работали.