class Zeus::S3Io

Constants

DEFAULT_PART_SIZE
  • Размер каждой части, кроме последней, должен быть не менее 5MB

  • Номер — это целое число в промежутке от 1 до 10000 включительно

Attributes

io[R]
part_size[R]

Public Class Methods

new(io, part_size: DEFAULT_PART_SIZE) click to toggle source

@param [File, StringIO, IO]

# File lib/zeus/s3_io.rb, line 15
def initialize(io, part_size: DEFAULT_PART_SIZE)
  @io = io
  @part_size = part_size
end

Public Instance Methods

upload(s3, bucket:, key:, **extra) { |100| ... } click to toggle source

@param s3 [Aws::S3::Client]

# File lib/zeus/s3_io.rb, line 21
def upload(s3, bucket:, key:, **extra, &block)
  if multipart?
    upload_multipart(s3, bucket: bucket, key: key, **extra, &block)
  else
    s3.put_object(bucket: bucket, key: key, body: io.read, **extra)
    yield(100) if block_given?
  end
end

Private Instance Methods

each_part(num: 1) { |read, num| ... } click to toggle source

yields parts bytes and number of a page

# File lib/zeus/s3_io.rb, line 68
def each_part(num: 1)
  until io.eof?
    yield(io.read(part_size), num)
    num += 1
  end
end
multipart?() click to toggle source
# File lib/zeus/s3_io.rb, line 75
def multipart?
  total_parts.nonzero?
end
total_parts() click to toggle source
# File lib/zeus/s3_io.rb, line 79
def total_parts
  io.size.fdiv(part_size).ceil
end
upload_multipart(s3, bucket:, key:, **extra) { |progress| ... } click to toggle source
# File lib/zeus/s3_io.rb, line 32
def upload_multipart(s3, bucket:, key:, **extra)
  multipart = s3.create_multipart_upload(bucket: bucket, key: key, **extra)
  parts = []

  each_part do |part, num|
    parts << s3.upload_part(
      body: part,
      bucket: bucket,
      content_length: part.bytesize,
      key: key,
      part_number: num,
      upload_id: multipart.upload_id
    )

    progress = (num.fdiv(total_parts) * 100).round
    progress = 100 if progress > 100

    yield(progress) if block_given?
  end

  s3.complete_multipart_upload(
    bucket: bucket,
    key: key,
    upload_id: multipart.upload_id,
    multipart_upload: {
      parts: parts.map.with_index  do |part, ix|
        {
          etag: part.etag,
          part_number: ix.next
        }
      end
    }
  )
end