diff --git a/app.rb b/app.rb index 8e8bab2..441aa4c 100644 --- a/app.rb +++ b/app.rb @@ -446,3 +446,48 @@ route :delete, :get, :patch, :post, :put, "/auth/basic", provides: "json" do jsonify({authenticated: true, user: @auth.username}, pretty:) end + +def human_size_to_bytes(size) + units = %i[b kb mb gb tb pb eb zb yb rb qb] + + number, unit = size.split(/(?<=\d)(?=[A-Za-z])/) + + raise ArgumentError, "the unit is not recognized" if unit.nil? + + number = Float(number) + unit = unit.downcase.to_sym + + exponent = units.find_index(unit) + + number *= (1024**exponent) + Integer(number.ceil) +end + +MAX_DOWNLOAD_SIZE = "1GB" + +get "/bytes/:size" do + size = params[:size] + n = [human_size_to_bytes(size), human_size_to_bytes(MAX_DOWNLOAD_SIZE)].min + + headers["content-type"] = "application/octet-stream" + headers["content-length"] = n + + headers["content-disposition"] = "attachment; filename=\"#{params[:f]}\"" if params.key? :f + + def generate_bytes(number, byte = "\x00", block_size = 4096) + raise ArgumentError, "'byte' must be 1 byte" unless byte.b.length == 1 + + bytes_written = 0 + block = byte * block_size + Enumerator.new do |g| + while bytes_written < number + remaining_bytes = number - bytes_written + bytes_to_write = [block_size, remaining_bytes].min + g.yield block[0, bytes_to_write] + bytes_written += bytes_to_write + end + end + end + + generate_bytes(Integer(n)) +end