@@ -30,47 +30,57 @@ def download(output_path, &block)
3030
3131 output_path . parent . mkpath
3232
33- headers = {
34- "Accept-Encoding" => "identity" ,
35- "User-Agent" => "Red Datasets/#{ VERSION } " ,
36- }
37- start = nil
38- partial_output_path = Pathname . new ( "#{ output_path } .partial" )
39- if partial_output_path . exist?
40- start = partial_output_path . size
41- headers [ "Range" ] = "bytes=#{ start } -"
42- end
43-
44- start_http ( @url , headers ) do |response |
45- if response . is_a? ( Net ::HTTPPartialContent )
46- mode = "ab"
47- else
48- start = nil
49- mode = "wb"
33+ n_retries = 0
34+ n_max_retries = 5
35+ begin
36+ headers = {
37+ "Accept-Encoding" => "identity" ,
38+ "User-Agent" => "Red Datasets/#{ VERSION } " ,
39+ }
40+ start = nil
41+ partial_output_path = Pathname . new ( "#{ output_path } .partial" )
42+ if partial_output_path . exist?
43+ start = partial_output_path . size
44+ headers [ "Range" ] = "bytes=#{ start } -"
5045 end
5146
52- base_name = @url . path . split ( "/" ) . last
53- size_current = 0
54- size_max = response . content_length
55- if start
56- size_current += start
57- size_max += start
58- yield_chunks ( partial_output_path , &block ) if block_given?
59- end
60- progress_reporter = ProgressReporter . new ( base_name , size_max )
61- partial_output_path . open ( mode ) do |output |
62- response . read_body do |chunk |
63- size_current += chunk . bytesize
64- progress_reporter . report ( size_current )
65- output . write ( chunk )
66- yield ( chunk ) if block_given?
47+ start_http ( @url , headers ) do |response |
48+ if response . is_a? ( Net ::HTTPPartialContent )
49+ mode = "ab"
50+ else
51+ start = nil
52+ mode = "wb"
53+ end
54+
55+ base_name = @url . path . split ( "/" ) . last
56+ size_current = 0
57+ size_max = response . content_length
58+ if start
59+ size_current += start
60+ size_max += start
61+ if block_given? and n_retries . zero?
62+ yield_chunks ( partial_output_path , &block )
63+ end
64+ end
65+ progress_reporter = ProgressReporter . new ( base_name , size_max )
66+ partial_output_path . open ( mode ) do |output |
67+ response . read_body do |chunk |
68+ size_current += chunk . bytesize
69+ progress_reporter . report ( size_current )
70+ output . write ( chunk )
71+ yield ( chunk ) if block_given?
72+ end
6773 end
6874 end
75+ FileUtils . mv ( partial_output_path , output_path )
76+ rescue Net ::ReadTimeout => error
77+ n_retries += 1
78+ retry if n_retries < n_max_retries
79+ raise
80+ rescue TooManyRedirects => error
81+ last_url = error . message [ /\A too many redirections: (.+)\z / , 1 ]
82+ raise TooManyRedirects , "too many redirections: #{ @url } .. #{ last_url } "
6983 end
70- FileUtils . mv ( partial_output_path , output_path )
71- rescue TooManyRedirects => error
72- last_url = error . message [ /\A too many redirections: (.+)\z / , 1 ]
73- raise TooManyRedirects , "too many redirections: #{ @url } .. #{ last_url } "
7484 end
7585
7686 private def start_http ( url , headers , limit = 10 , &block )
0 commit comments