class Tus::Client
Constants
- CHUNK_SIZE
100 MiB is ok for now…
- NUM_RETRIES
- TUS_VERSION
- VERSION
Public Class Methods
new(server_url)
click to toggle source
# File lib/tus/client.rb, line 15 def initialize(server_url) @server_uri = URI.parse(server_url) # better to open the connection now @http = Net::HTTP.start(@server_uri.host, @server_uri.port) # we cache this value for further use @capabilities = capabilities end
Public Instance Methods
upload(file_path)
click to toggle source
# File lib/tus/client.rb, line 24 def upload(file_path) raise 'No such file!' unless File.file?(file_path) file_name = File.basename(file_path) file_size = File.size(file_path) io = File.open(file_path, 'rb') upload_by_io(file_name: file_name, file_size: file_size, io: io) end
upload_by_io(file_name:, file_size:, io:)
click to toggle source
# File lib/tus/client.rb, line 34 def upload_by_io(file_name:, file_size:, io:) raise 'Cannot upload a stream of unknown size!' unless file_size uri = create_remote(file_name, file_size) # we use only parameters that are known to the server offset, length = upload_parameters(uri) chunks = Enumerator.new do |yielder| loop do chunk = io.read(CHUNK_SIZE) break unless chunk yielder << chunk end end begin offset = chunks.lazy.inject(offset) do |current_offset, chunk| upload_chunk(uri, current_offset, chunk) end rescue StandardError raise 'Broken upload! Cannot send a chunk!' end raise 'Broken upload!' unless offset == length io.close end
Private Instance Methods
capabilities()
click to toggle source
# File lib/tus/client.rb, line 66 def capabilities raise 'Uninitialized connection!' unless @http response = @http.options(@server_uri.request_uri) response['Tus-Extension']&.split(',') end
create_remote(file_name, file_size)
click to toggle source
# File lib/tus/client.rb, line 74 def create_remote(file_name, file_size) unless @capabilities.include?('creation') raise 'New file uploading is not supported!' end request = Net::HTTP::Post.new(@server_uri.request_uri) request['Content-Length'] = 0 request['Upload-Length'] = file_size request['Tus-Resumable'] = TUS_VERSION request['Upload-Metadata'] = "filename: #{Base64.strict_encode64(file_name)},is_confidential" response = nil NUM_RETRIES.times do begin response = @http.request(request) break rescue StandardError next end end unless response.is_a?(Net::HTTPCreated) raise 'Cannot create a remote file!' end location_url = response['Location'] raise 'Malformed server response: missing \'Location\' header' unless location_url URI.parse(location_url).path end
upload_chunk(uri, offset, chunk)
click to toggle source
# File lib/tus/client.rb, line 116 def upload_chunk(uri, offset, chunk) request = Net::HTTP::Patch.new(uri) request['Content-Type'] = 'application/offset+octet-stream' request['Upload-Offset'] = offset request['Tus-Resumable'] = TUS_VERSION request.body = chunk response = nil NUM_RETRIES.times do begin response = @http.request(request) break rescue StandardError next end end raise 'Cannot upload a chunk!' unless response.is_a?(Net::HTTPNoContent) resulting_offset = response['Upload-Offset'].to_i unless resulting_offset == offset + chunk.size raise 'Chunk upload is broken!' end resulting_offset end
upload_parameters(uri)
click to toggle source
# File lib/tus/client.rb, line 107 def upload_parameters(uri) request = Net::HTTP::Head.new(uri) request['Tus-Resumable'] = TUS_VERSION response = @http.request(request) [response['Upload-Offset'], response['Upload-Length']].map(&:to_i) end