Sha256: bb5b171f7ed8480d38aaa1a866bed5cc53cd7e54edadbab924c3179f6bd8d20d

Contents?: true

Size: 1.62 KB

Versions: 1

Compression:

Stored size: 1.62 KB

Contents

require "open-uri"
require "tempfile"
require "uri"

module Down
  class Error < StandardError; end
  class TooLarge < Error; end
  class NotFound < Error; end

  module_function

  def download(url, options = {})
    url = URI.encode(URI.decode(url))

    downloaded_file = URI(url).open(
      "User-Agent" => "Down/1.0.0",
      content_length_proc: proc { |size|
        raise Down::TooLarge if size && options[:max_size] && size > options[:max_size]
      },
      progress_proc: proc { |current_size|
        raise Down::TooLarge if options[:max_size] && current_size > options[:max_size]
        options[:progress].call(current_size) if options[:progress]
      },
      open_timeout: options[:timeout],
    )

    # open-uri will return a StringIO instead of a Tempfile if the filesize
    # is less than 10 KB, so if it happens we convert it back to Tempfile.
    if downloaded_file.is_a?(StringIO)
      stringio = downloaded_file
      downloaded_file = copy_to_tempfile("open-uri", stringio)
      OpenURI::Meta.init downloaded_file, stringio
    end

    downloaded_file.extend DownloadedFile
    downloaded_file

  rescue => error
    raise if error.instance_of?(RuntimeError) && error.message !~ /redirection/
    raise if error.is_a?(Down::Error)
    raise Down::NotFound, error.message
  end

  def copy_to_tempfile(basename, io)
    tempfile = Tempfile.new(basename, binmode: true)
    IO.copy_stream(io, tempfile.path)
    io.rewind
    tempfile
  end

  module DownloadedFile
    def original_filename
      path = base_uri.path
      path = URI.decode(path)
      File.basename(path) unless path.empty? || path == "/"
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
down-1.0.0 lib/down.rb