2010-06-22 22 views
10

Ich entwickle eine Sinatra-App, die aus einem Upload-Formular besteht, mit einem Fortschrittsbalken, der angibt, wie viel von dem Upload abgeschlossen wurde. Der Prozess, wie von ryan dahl beschrieben, ist die folgende:Sinatra, Fortschrittsbalken im Upload-Formular

HTTP Upload Fortschrittsbalken sind eher obfuscated- sie in der Regel ein Prozess einbeziehen auf dem Server ausgeführt Spur der Größe des tempfile zu halten, dass der HTTP-Server schreibt zu, dann wird auf der Client-Seite während des Uploads alle paar Sekunden ein AJAX-Aufruf an den Server gesendet, um nach dem Fortschritt des Uploads zu fragen.

Jeder Upload hat eine zufällige session-id und Spur des Vereins zu halten i verwenden eine class variable in meiner app (ich weiß, das ist schrecklich - wenn Sie bessere Ideen haben, bitte sagen Sie mir)

configure do 
    @@assoc = {} 
end 

Ich habe eine POST Route für den Upload und eine GET eine für die AJAX-Abfrage. In der Route POST ich die Zuordnung von session-id, Tempfile und Gesamtgröße speichern.

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 

Im GET Route berechnen i den Prozentsatz bezogen auf die Tempfile ‚s aktuelle Größe:

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 

Das Problem ist, dass, bis die POST Anforderung nicht abgeschlossen ist (dh, nachdem es hat Lesen Sie alle Tempfile) die h.nil? gibt true zurück, was nicht wirklich Sinn macht, da ich gerade @@assoc[@sid] einen Wert in der anderen Route zugewiesen habe.

Also, was fehlt mir hier?

EDIT: Ich habe versucht,

  • set :reload, false
  • set :environment, :production
  • config { @@assoc ||= {} }
  • Ich versuchte auch, eine relationale db es (SQLite mit DataMapper) werfen

Weder funktioniert.

+0

Die '@@ assoc [@sid] = {...' Zeile fehlt am Ende ein '}'. – Adrian

+0

behoben, danke :) – asymmetric

Antwort

4

sein Ich glaube, ich habe, was das Problem ist:

tmp = params[:file][:tempfile] nicht zurück, bis die Datei vollständig empfangen wurde.

+0

true, haben Sie eine Problemumgehung für dieses Problem gefunden? – dombesz

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

sollte

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

Ja, es ist ein Tippfehler in der Frage, es ist in Ordnung in der realen App. danke trotzdem für die Berichterstattung. – asymmetric