Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'net/ftp'
- require 'tmpdir'
- require 'thwait'
- DEBUG = !ENV.fetch('DEBUG', '').empty?
- CONCURRENT = ENV.fetch('CONCURRENT').to_i
- FTP_HOST = ENV.fetch('FTP_HOST')
- FTP_PORT = ENV.fetch('FTP_PORT').to_i
- FTP_USER = ENV.fetch('FTP_USER')
- FTP_PASS = ENV.fetch('FTP_PASS')
- FTP_PATH = ENV.fetch('FTP_PATH')
- def establish_connection
- Net::FTP.new(FTP_HOST, port: FTP_PORT, username: FTP_USER, password: FTP_PASS, passive: true, debug_mode: DEBUG)
- end
- content_size = establish_connection.size(FTP_PATH)
- page_size = (content_size.to_f / CONCURRENT).ceil
- Dir.mktmpdir do |dir|
- threads = []
- CONCURRENT.times do |i|
- offset = page_size * i
- next if offset >= content_size
- threads << Thread.start(i) do |t|
- File.open("#{dir}/#{t}", 'wb') do |page|
- ftp = establish_connection
- ftp.resume = true
- retrieved = 0
- ftp.retrbinary("RETR #{FTP_PATH}", Net::FTP::DEFAULT_BLOCKSIZE, offset) do |chunk|
- rest = page_size - retrieved
- retrievable = [rest, chunk.bytesize].min
- break if retrievable <= 0
- retrieved += page.write(chunk[0, retrievable])
- end
- end
- end
- end
- ThreadsWait.all_waits(*threads)
- File.open('downloaded', 'wb') do |output|
- CONCURRENT.times do |i|
- path = "#{dir}/#{i}"
- next unless File.exist?(path)
- IO.copy_stream(path, output)
- end
- end
- end
- __END__
- ### e.g. 495MB CentOS ISO file
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
- 1: 165.29 real 5.34 user 4.74 sys
- 3: 99.68 real 5.23 user 6.12 sys
- 5: 88.19 real 5.56 user 7.43 sys
Add Comment
Please, Sign In to add comment