Skip to content

Instantly share code, notes, and snippets.

@Jeweller-Tsai
Created May 26, 2012 16:06
Show Gist options
  • Save Jeweller-Tsai/2794445 to your computer and use it in GitHub Desktop.
Save Jeweller-Tsai/2794445 to your computer and use it in GitHub Desktop.
Using HTTP range to download a file separately
require "net/http"
require 'uri'
def download(uri_str)
uri = URI uri_str
Net::HTTP.new(uri.host, uri.port).start do |http|
head = http.request_head uri.path
length = head.content_length
puts length
return puts('Invalid URL') unless head.is_a? Net::HTTPSuccess
req1 = Net::HTTP::Get.new uri.request_uri
req2 = Net::HTTP::Get.new uri.request_uri
req1['Range'] = "bytes=0-#{length/2-1}"
req2['Range'] = "bytes=-#{length/2}"
parts = {}
threads = []
threads << Thread.new(http) { |h| parts[1] = h.request req1 }
threads << Thread.new(http) { |h| parts[2] = h.request req2 }
File.open('song.mp3', 'w') do |f|
threads.each { |th| th.join }
f.write parts[1].body
f.write parts[2].body
f.close
end
end
end
uri = 'http://file16.top100.cn/201205262345/517316BC2FC86C1BEBF2BA1C71133352/Special_329225/%E4%BD%A0%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84%E4%BA%8B.mp3'
download uri
# The code above may cause exception "`rescue in rbuf_fill': Timeout::Error (Timeout::Error)", I tried to set # the `read_timeout`, but couldn't solve this problem.
# If I join the thread immediately, `Thread.new(http) { |h| parts[1] = h.request req1 }.join`, it worked. But # it make no sense, because it become sequential.
@loveybot
Copy link

Yay Ruby!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment