2010-06-22 11 views
10

Je suis en train de développer une application Sinatra qui consiste en un formulaire de téléchargement, avec une barre de progression indiquant la quantité de téléchargement terminée. Le processus, tel que décrit par ryan dahl, est la suivante:Sinatra, barre de progression dans le formulaire de téléchargement

HTTP télécharger des barres de progression sont plutôt obfuscated- ils impliquent généralement un processus en cours d'exécution sur la piste en gardant serveur de la taille du fichier temporaire que le serveur HTTP est en train d'écrire à, alors du côté client un appel AJAX est fait toutes les deux secondes au serveur pendant le téléchargement pour demander la progression du téléchargement.

Chaque téléchargement a un session-id aléatoire, et de garder une trace de l'association i employer un class variable dans mon application (je sais, c'est horrible - si vous avez de meilleures idées, s'il vous plaît me dire)

configure do 
    @@assoc = {} 
end 

J'ai un POST itinéraire pour le téléchargement, et un GET pour l'interrogation AJAX. A l'intérieur de l'itinéraire POST, j'ai enregistré l'association session-id, Tempfile et la taille totale.

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 

Dans la route GET, je calcule le pourcentage en fonction de la taille actuelle de 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 

Le problème est que tant que la demande POST n'a pas terminé (après qu'il a lire tous les Tempfile) le h.nil? renvoie true, ce qui n'a pas vraiment de sens car je viens d'attribuer @@assoc[@sid] une valeur dans l'autre route.

Alors, qu'est-ce qui me manque ici?

EDIT: J'ai essayé

  • set :reload, false
  • set :environment, :production
  • config { @@assoc ||= {} }
  • J'ai aussi essayé de lancer une db relationnelle à elle (SQLite avec DataMapper)

Aucun travail.

+0

La ligne '@@ assoc [@sid] = {...' manque un '}' à la fin. – Adrian

+0

fixe, merci :) – asymmetric

Répondre

4

Je pense que je suis ce que le problème est:

tmp = params[:file][:tempfile] ne retourne pas jusqu'à ce que le fichier a été entièrement reçu.

+0

vrai, avez-vous trouvé une solution de contournement à ce problème? – dombesz

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

devrait être

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

ouais, c'est une faute de frappe dans la question, c'est ok dans la vraie application. merci quand même pour les rapports. – asymmetric