class

UploadIO

Inherits IO < Reference < Object

UploadIO supports chunked uploads with a built-in progress callback and provides upload cancellation through either a callback or direct method call.

require "upload_io"
require "http/client"

file = File.open("/path/to/file")
size = file.size
uploaded_total = 0

upload_io = UploadIO.new(file, 4096, ->(uploaded_chunk : Int32) {
  uploaded_total += uploaded_chunk
  puts "Uploaded: #{uploaded_total} / #{size} bytes"
})

headers = HTTP::Headers{
  "Content-Type"   => "application/octet-stream",
  "Content-Length" => size.to_s,
}

response = HTTP::Client.post("http://example.com/upload", headers: headers, body: upload_io)
puts "Upload complete! Response: #{response.status_code}"

Constants

CHUNK_SIZE = 4096
VERSION = {{ (`shards version /tmp/tmp.ADEGfm/src/src`).chomp.stringify }}

Constructors

new(data : HTTP::Client::BodyType, chunk_size : Int32, on_progress : Proc(Int32, Nil) | Nil = nil, should_cancel : Proc(Bool) | Nil = nil, *, max_speed : Int64 | Nil = nil)

Creates a new UploadIO with given arguments.

  • data - the upload data source
  • chunk_size - the maximum size of each chunk for Bytes and String data
  • on_progress - optional callback to track progress
  • should_cancel - optional callback to control upload cancellation
  • max_speed - optional maximum upload speed in bytes per second
Source
new(data : HTTP::Client::BodyType, chunk_size : Int32 = CHUNK_SIZE, &block : self -> )

Creates a new UploadIO with a block for configuration.

file = File.open("/path/to/file")
size = file.size
uploaded_total = 0

upload_io = UploadIO.new(file) do |io|
  io.on_progress ->(uploaded_chunk : Int32) do
    uploaded_total += uploaded_chunk
    puts "Uploaded: #{uploaded_total} / #{size} bytes"
  end

  io.should_cancel -> { uploaded_total >= size / 2 }
  io.max_speed = 125_000 # 1 Mbps
end

response = HTTP::Client.post("http://example.com/upload", body: upload_io)
Source
new(data : HTTP::Client::BodyType, on_progress : Proc(Int32, Nil) | Nil = nil, should_cancel : Proc(Bool) | Nil = nil, *, max_speed : Int64 | Nil = nil)
Source

Instance methods

cancel

Cancels the upload process. After calling this method:

  • Subsequent reads will return 0 bytes
  • If the data source is an IO, it will be closed
  • The upload cannot be resumed
Source
cancelled?

Returns true if the upload has been cancelled

Source
max_speed

Maximum upload speed in bytes per second. If nil, no speed limit is applied.

Source
max_speed=(max_speed : Int64 | Nil)
Source
on_progress(on_progress : Proc(Int32, Nil))

Optional callback function that receives the size of each uploaded chunk.

file = File.open("/path/to/file")
size = file.size
uploaded_total = 0

upload_io = UploadIO.new(file)
upload_io.on_progress ->(uploaded_chunk : Int32) do
  uploaded_total += uploaded_chunk
  puts "Uploaded: #{uploaded_total} / #{size} bytes"
end

response = HTTP::Client.post("http://example.com/upload", body: upload_io)
Source
pause

Pauses the upload process. While paused:

  • Subsequent reads will block until resume is called
  • The upload can be resumed using the resume method
Source
paused?

Returns true if the upload is currently paused

Source
read(slice : Bytes) : Int32

Reads the next chunk of data and copies it into the provided buffer.

This method is called automatically by HTTP::Client when sending data. It reads up to chunk_size bytes for Bytes and String data. Wrapped IO sources are read directly into the provided buffer, so their read size is controlled by the caller's buffer size.

Returns the number of bytes that will be sent to the server (not the total send bytes), which is 0 if and only if there is no more data to reads (so checking for 0 is the way to detect end of file).

Since UploadIO only provides data to HTTP::Client, we can only track the amount of data read and not the actual bytes transmitted to the server.

Source
resume

Resumes a paused upload. After calling this method:

  • Subsequent reads will continue from where they left off
Source
rewind

Rewinds this IO. By default this method raises, but including types may implement it.

Source
should_cancel(should_cancel : Proc(Bool))

Optional callback function that determines if the upload should be cancelled. Return true to cancel the upload.

file = File.open("/path/to/file")
start_time = Time.instant

upload_io = UploadIO.new(file)
# Stop upload after 5 seconds
upload_io.should_cancel -> { (Time.instant - start_time).total_seconds > 5 }

response = HTTP::Client.post("http://example.com/upload", body: upload_io)
Source
uploaded

Tracks the total bytes uploaded so far.

Source
write(slice : Bytes) : Nil

Required method by IO but not used in UploadIO.

UploadIO is read-only, so write does nothing.

Source