2014-06-13 14 views
5

Io uso il seguente frammento di Ruby per scaricare a 8.9MB file.Zlib :: BufError quando si utilizza la progressbar/ruby-progressbar gemma

require 'open-uri' 
require 'net/http' 
require 'uri' 

def http_download_no_progress_bar(uri, filename) 
    uri.open(read_timeout: 500) do |file| 
    open filename, 'w' do |io| 
     file.each_line do |line| 
     io.write line 
     end 
    end 
    end 
end 

voglio aggiungere la progressbar gemma di visualizzare il processo di download:

require 'open-uri' 
require 'progressbar' 
require 'net/http' 
require 'uri' 

def http_download_with_progressbar(uri, filename) 
    progressbar = nil 
    uri.open(
    read_timeout: 500, 
    content_length_proc: lambda { |total| 
    if total && 0 < total.to_i 
     progressbar = ProgressBar.new("...", total) 
     progressbar.file_transfer_mode 
    end 
    }, 
    progress_proc: lambda { |step| 
     progressbar.set step if progressbar 
    } 
) do |file| 
    open filename, 'w' do |io| 
     file.each_line do |line| 
     io.write line 
     end 
    end 
    end 
end 

Tuttavia, ora non riesce con il seguente errore:

/home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:357:in `finish': 
buffer error (Zlib::BufError)oooooo | 8.0MB 8.6MB/s ETA: 0:00:00 

    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:357:in `finish' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:262:in `ensure in inflater' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:262:in `inflater' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:274:in `read_body_0' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:201:in `read_body' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:328:in `block (2 levels) in open_http' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1415:in `block (2 levels) in transport_request' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:162:in `reading_body' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1414:in `block in transport_request' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1405:in `catch' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1405:in `transport_request' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1378:in `request' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:319:in `block in open_http' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:853:in `start' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:313:in `open_http' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:724:in `buffer_open' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:210:in `block in open_loop' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:208:in `catch' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:208:in `open_loop' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:149:in `open_uri' 
    from /home/user/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/open-uri.rb:704:in `open' 

Nel frattempo ho anche provato il ruby-progressbar gemma:

require 'open-uri' 
require 'ruby-progressbar' 
require 'net/http' 
require 'uri' 

def http_download_with_ruby_progressbar(uri, filename) 
    progressbar = nil 
    uri.open(
    read_timeout: 500, 
    content_length_proc: lambda { |total| 
     if total && 0 < total.to_i 
     progressbar = ProgressBar.create(title: filename, total: total) 
     end 
     }, 
     progress_proc: lambda { |step| 
     progressbar.progress = step if progressbar 
     } 
) do |file| 
    open filename, 'w' do |io| 
     file.each_line do |line| 
     io.write line 
     end 
    end 
    end 
end 

Non riesce con lo stesso errore . Ecco il associated issue per il problema.

+0

TIL ['open-uri'] (http://ruby-doc.org/stdlib/libdoc/open-uri/rdoc/OpenURI/OpenRead.html#method-i-open) ha alcune opzioni nette (e scusa non posso aiutarti con il tuo problema) ... – DMKE

risposta

4

Il problema è il file che si sta tentando di scaricare poiché ogni metodo funziona con this file: https://androidnetworktester.googlecode.com/files/1mb.txt.

Il problema è che il file è più grande di quello che dice di essere. Il content_length_proc dice che èbyte (8.15MB) mentre è 101187668 byte (96.5MB) (controllare con ls dopo aver scaricato il file). Ora ho un'alternativa che non si blocca e ti dà una progressbar:

def http_download_with_words(uri, filename) 
    bytes_total = nil 
    uri.open(
      read_timeout: 500, 
      :content_length_proc => lambda{|content_length| 
      bytes_total = content_length}, 
      :progress_proc => lambda{|bytes_transferred| 
      if bytes_total 
       # Print progress 
       print("\r#{bytes_transferred}/#{bytes_total}") 
      else 
       # We don’t know how much we get, so just print number 
       # of transferred bytes 
       print("\r#{bytes_transferred} (total size unknown)") 
      end 
      } 
      ) do |file| 
    open filename, 'w' do |io| 
     file.each_line do |line| 
     io.write line 
     end 
    end 
    end 
end 

http_download_with_words(URI('http://data.wien.gv.at/daten/geo?service=WFS&request=GetFeature&version=1.1.0&typeName=ogdwien%3aBAUMOGD&srsName=EPSG:4326'), 'temp.txt') 

che è abbastanza auto-esplicativo, (visto here.)

Ora la parte non sono stato in grado di capire è come esattamente la gemma progressbar interferisce con ZLib. La maggior parte delle cose sembra funzionare bene all'interno del procs (ad esempio se si stampano delle cose casuali) quindi presumo che entrambi questi progressbar facciano qualcosa di strano al completamento che in qualche modo incasina il trasferimento. Sarei molto interessato se qualcuno riuscisse a capire perché è così?

+0

Bella ricerca. Non ho notato la differenza nella dimensione del file. Peccato che non funzioni con una delle gemme. Purtroppo il manutentore sembra ignorare le mie richieste. Cercherò di integrare la tua soluzione entro i prossimi giorni. – JJD

+0

L'ho provato ora (dopo le vacanze). Funziona bene. In questo caso posso rinunciare alla barra di avanzamento visivo. Grazie. – JJD

2

Nei miei test quando ciò si è verificato era dovuto al rilancio in #set. Per quanto riguarda il motivo per cui si verifica un errore in Zlib, non è chiaro. Forse qualche strana gestione delle eccezioni. Nel mio caso ho fatto "progbar.set (count) rescue nil" per eliminare il problema.

Problemi correlati