Я разрабатываю приложение 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
's текущий размер:
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 ||= {} }
- Я также пытался бросить реляционныйдБ у него (SQLite с DataMapper)
Ни сработало.