2010-06-22 14 views
10

Estoy desarrollando una aplicación Sinatra que consiste en un formulario de carga, con una barra de progreso que indica cuánto de la carga se ha completado. El proceso, según lo descrito por ryan dahl, es el siguiente:Sinatra, barra de progreso en el formulario de carga

HTTP cargar barras de progreso son más bien obfuscated- por lo general implican un proceso que se ejecuta en el servidor de no perder de vista el tamaño del archivo temporal que el servidor HTTP está escribiendo a, luego en el lado del cliente, se realiza una llamada AJAX cada dos segundos al servidor durante la carga para solicitar el progreso de la carga.

Cada carga tiene una session-id al azar, y hacer un seguimiento de la asociación Empleo una class variable en mi aplicación (lo sé, eso es horrible - si tienes mejores ideas, por favor dime)

configure do 
    @@assoc = {} 
end 

Tengo una ruta POST para la carga, y una GET para el sondeo AJAX. Dentro de la ruta POST guardo la asociación de session-id, Tempfile, y el tamaño total.

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 

En la ruta GET, i calcular el porcentaje basado en el tamaño actual de la 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 

El problema es que hasta que la solicitud POST no ha completado (es decir, después de que ha lea todos los Tempfile) el h.nil? devuelve true, lo que realmente no tiene sentido ya que acabo de asignar @@assoc[@sid] un valor en la otra ruta.

Entonces, ¿qué es lo que me falta aquí?

EDIT: He intentado

  • set :reload, false
  • set :environment, :production
  • config { @@assoc ||= {} }
  • También probé lanzar una base de datos relacional en la que (con SQLite DataMapper)

Ninguno funcionó.

+0

La línea '@@ assoc [@sid] = {...' no tiene un '}' al final. – Adrian

+0

arreglado, gracias :) – asymmetric

Respuesta

4

Creo que tengo lo que el problema es:

tmp = params[:file][:tempfile] no vuelve hasta que el archivo se ha recibido completamente.

+0

cierto, ¿ha encontrado una solución a este problema? – dombesz

1
@@assoc[@sid] = { :file => tmp, :size => env['CONTENT_LENGTH'] } 

debería ser

@@assoc[params[:sid]] = { :file => tmp, :size => env['CONTENT_LENGTH'] } 
+0

sí, es un error tipográfico en la pregunta, está bien en la aplicación real. gracias de todos modos por informar. – asymmetric