class Google::Apis::Core::DownloadCommand

Streaming/resumable media download support

Constants

RANGE_HEADER

Attributes

download_dest[RW]

File or IO to write content to @return [String, File, write]

Public Instance Methods

execute_once(client, &block) click to toggle source

Execute the upload request once. Overrides the default implementation to handle streaming/chunking of file content.

@private @param [Hurley::Client] client

HTTP client

@yield [result, err] Result or error if block supplied @return [Object] @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification @raise [Google::Apis::AuthorizationError] Authorization is required

# File lib/google/apis/core/download.rb, line 67
def execute_once(client, &block)
  client.get(@download_url || url) do |req|
    apply_request_options(req)
    check_if_rewind_needed = false
    if @offset > 0
      logger.debug { sprintf('Resuming download from offset %d', @offset) }
      req.header[RANGE_HEADER] = sprintf('bytes=%d-', @offset)
      check_if_rewind_needed = true
    end
    req.on_body(200, 201, 206) do |res, chunk|
      check_status(res.status_code, chunk) unless res.status_code.nil?
      if check_if_rewind_needed && res.status_code != 206
        # Oh no! Requested a chunk, but received the entire content
        # Attempt to rewind the stream
        @download_io.rewind
        check_if_rewind_needed = false
      end

      logger.debug { sprintf('Writing chunk (%d bytes)', chunk.length) }
      @offset += chunk.length
      @download_io.write(chunk)
      @download_io.flush
    end
  end
  if @close_io_on_finish
    result = nil
  else
    result = @download_io
  end
  success(result, &block)
rescue => e
  error(e, rethrow: true, &block)
end
prepare!() click to toggle source

Ensure the download destination is a writable stream.

@return [void]

Calls superclass method Google::Apis::Core::ApiCommand#prepare!
# File lib/google/apis/core/download.rb, line 34
def prepare!
  @state = :start
  @download_url = nil
  @offset = 0
  if download_dest.respond_to?(:write)
    @download_io = download_dest
    @close_io_on_finish = false
  elsif download_dest.is_a?(String)
    @download_io = File.open(download_dest, 'wb')
    @close_io_on_finish = true
  else
    @download_io = StringIO.new('', 'wb')
    @close_io_on_finish = false
  end
  super
end
release!() click to toggle source

Close IO stream when command done. Only closes the stream if it was opened by the command.

# File lib/google/apis/core/download.rb, line 52
def release!
  @download_io.close if @close_io_on_finish
end