2014-06-13 14 views
5

Używam następującego kodu Ruby do pobrania a 8.9MB file.Zlib :: BufError podczas korzystania z paska postępu/ruby ​​- pasek postępu gem

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 

Chcę dodać progressbar gem wizualizować proces pobierania:

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 

Jednak teraz nie powiedzie się z powodu następującego błędu:

/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' 

Tymczasem ja też próbowałem ruby-progressbar gem:

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 

Nie powiedzie się z tym samym błędem . Oto associated issue dla problemu.

+0

TIL ['open-uri'] (http://ruby-doc.org/stdlib/libdoc/open-uri/rdoc/OpenURI/OpenRead.html#method-i-open) ma kilka fajnych opcji (i przepraszam, nie mogę pomóc z twoim problemem) ... – DMKE

Odpowiedz

4

Problem to plik, który próbujesz pobrać, ponieważ każda metoda działa z this file: https://androidnetworktester.googlecode.com/files/1mb.txt.

Problem polega na tym, że plik jest większy niż jest w rzeczywistości. Content_length_proc mówi, że jest to 8549968 bajtów (8.15MB), natomiast jest to 101187668 bajtów (96.5MB) (sprawdź po ls po pobraniu pliku). Teraz mam alternatywę, która nie psuje i daje 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') 

co jest dość oczywiste, (obserwowane here.)

teraz część I nie były w stanie zorientować się, jest to, jak dokładnie gem gemu pasuje do ZLib. Większość rzeczy wydaje się działać dobrze w procach (np. Po wydrukowaniu losowych rzeczy), więc zakładam, że oba te paski postępu robią coś dziwnego po ukończeniu, które w jakiś sposób zakłóca transfer. Byłbym bardzo zainteresowany, gdyby ktoś mógł zrozumieć, dlaczego tak jest?

+0

Niezłe badania. Nie zauważyłem różnicy w rozmiarze pliku. Szkoda, że ​​nie działa z jednym z klejnotów. Niestety opiekun wydaje się ignorować moje prośby. Spróbuję zintegrować twoje rozwiązanie w ciągu następnych dni. – JJD

+0

Wypróbowałem to teraz (po wakacjach). Działa dobrze. W takim przypadku mogę zrezygnować z wizualnego paska postępu. Dziękuję Ci. – JJD

2

Podczas moich testów, kiedy do tego doszło, było to spowodowane podniesieniem w #set. Jeśli chodzi o przyczyny niepowodzenia w Zlib, nie jest to jasne. Być może jakiś dziwny sposób obsługi wyjątków. W moim przypadku zrobiłem "progbar.set (count) rescue nil", aby pozbyć się problemu.

Powiązane problemy