Я разрабатываю приложение Sinatra, которое состоит из формы загрузки с индикатором выполнения, указывающим, сколько из загрузки завершилось. Процесс, как описано ryan dahl, следующий:
Индикаторы выполнения загрузки HTTP скорее запутываются - они обычно включают процесс, работающий на сервере, отслеживающем размера tempfile, который сервер HTTP пишет в, затем на стороне клиента, которую вызов Ajax выполняется каждая пара секунды к серверу во время загрузки для просьбы прогресс загрузки.
Каждая загрузка имеет случайное session-id
, и отслеживать ассоциацию я использую a class variable
в моем приложении (я знаю, это ужасно - если у Вас есть лучшие идеи, скажите мне),
configure do
@@assoc = {}
end
У меня есть a POST
маршрут для загрузки и a 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
, который действительно не имеет смысла, поскольку я только что присвоился @@assoc[@sid]
значение в другом маршруте.
Так, что я пропускаю здесь?
Править: Я попробовал
set :reload, false
set :environment, :production
config { @@assoc ||= {} }
Ни один не работал.
Думаю, я понял, в чем проблема:
tmp = params [: file] [: tempfile]
не возвращается, пока файл не будет полностью получен.
@@assoc[@sid] = { :file => tmp, :size => env['CONTENT_LENGTH'] }
должно быть
@@assoc[params[:sid]] = { :file => tmp, :size => env['CONTENT_LENGTH'] }