2015-07-02 1 views
0

Я использую следующую функцию на Ruby для загрузки различных файлов через HTTP:Как загрузить задержанный файл через HTTP в Ruby?

def http_download(uri, filename) 
    bytes_total = nil 
    begin 
    uri.open(
     read_timeout: 500, 
     content_length_proc: lambda { |content_length| 
     bytes_total = content_length 
     }, 
     progress_proc: lambda { |bytes_transferred| 
     if bytes_total 
      print("\r#{bytes_transferred} of #{bytes_total} bytes") 
     else 
      print("\r#{bytes_transferred} bytes (total size unknown)") 
     end 
     } 
    ) do |file| 
     open filename, 'w' do |io| 
     file.each_line do |line| 
      io.write line 
     end 
     end 
    end 
    rescue => e 
    puts e 
    end 
end 

Я также хочу, чтобы загрузить файлы (csv, kml, zip, geojson) от this website. Однако есть какая-то задержка настроена. Когда я нажимаю ссылку загрузки в браузере, она занимает немного, пока не появится окно загрузки. Я полагаю, что файл должен быть обработан на сервере, прежде чем он сможет обслуживаться.

Как я могу изменить свой сценарий, чтобы учесть задержку?

Я бегу Ruby 2.2.2.

+0

Привет, что ваша версия Ruby? Я запускаю ваш код с помощью Ruby 2.2.2, получил исключение из «private method» open «called». И я открыл веб-сайт, кнопка «Загрузить набор данных», которую вы нажимаете? Я не столкнулся с ** задержкой **, которую вы упомянули, это только URL-адрес веб-сайта, который добавляет '.csv',' .kml', '.zip' и несколько параметров запроса. – ifyouseewendy

+0

Да, последняя версия. Да, ссылки скрыты под кнопкой «Загрузить набор данных». Может быть, они теперь задерживают его на сервере, когда я его нажал. Возможно, попробуйте другой набор данных. – JJD

+0

Я обнаружил, что для набора данных при первом запросе он возвращает JSON, который представляет статус, например. '{status:" processing ", processing_time: 0, count: 0}', '{status:" processing ", processing_time: 9.58, count: 0}'. После обработки вы загрузите файл. Поэтому я думаю, что вы можете просто добавить судью и повторить попытку обработки. – ifyouseewendy

ответ

2

Вот модификация согласно сообщению и комментарий:

require 'open-uri' 

def http_download(uri, filename) 
    bytes_total = nil 
    index = 1 
    begin 
    open(
     uri, 
     read_timeout: 500, 
     content_length_proc: lambda { |content_length| 
     bytes_total = content_length 
     }, 
     progress_proc: lambda { |bytes_transferred| 
     if bytes_total 
      print("\r#{bytes_transferred} of #{bytes_total} bytes") 
     else 
      print("\r#{bytes_transferred} bytes (total size unknown)") 
     end 
     } 
    ) do |io| 
     # if "application/json" == io.content_type 
     if io.is_a? StringIO 
     raise " --> Failed, server is processing. Retry the request ##{index}" 
     else # Tempfile 
     puts "\n--> Succeed, writing to #{filename}" 
     File.open(filename, 'w'){|wf| wf.write io.read} 
     end 
    end 
    rescue => e 
    puts e 
    return if e.is_a? OpenURI::HTTPError # Processing error 

    index += 1 
    return if index > 10 

    sleep index and retry 
    end 
end 
+0

Удивительный! Один незначительный случай, который я заметил, - это когда файл загрузки JSON - я добавил ссылку выше. – JJD

+1

Право, только что обновленный код. – ifyouseewendy

+0

Отлично! Я попробовал сценарий на [другом сервере] (http://geoportaal.ddh.opendata.arcgis.com/datasets/053dd72ba7c346be9c648210b6af2352_7) ([kml] (http://geoportaal.ddh.opendata.arcgis.com/datasets/053dd72ba7c346be9c648210b6af2352_7 .kml)). По какой-то причине он там не работает, хотя, похоже, такой же механизм задержки. Вы видите причину? – JJD