lib/down.rb in down-2.3.5 vs lib/down.rb in down-2.3.6

- old
+ new

@@ -1,6 +1,7 @@ require "down/version" +require "down/chunked_io" require "open-uri" require "net/http" require "tempfile" require "fileutils" @@ -79,10 +80,11 @@ def stream(url, options = {}) warn "Down.stream is deprecated and will be removed in Down 3. Use Down.open instead." io = open(url, options) io.each_chunk { |chunk| yield chunk, io.size } + io.close end def open(url, options = {}) uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) @@ -111,15 +113,16 @@ end end end response = request.resume - content_length = Integer(response["Content-Length"]) if response["Content-Length"] - chunks = response.to_enum(:read_body) - close_connection = -> { request.resume } - ChunkedIO.new(size: content_length, chunks: chunks, on_close: close_connection) + ChunkedIO.new( + chunks: response.enum_for(:read_body), + size: response["Content-Length"] && response["Content-Length"].to_i, + on_close: -> { request.resume }, + ) end def copy_to_tempfile(basename, io) tempfile = Tempfile.new(["down", File.extname(basename)], binmode: true) if io.is_a?(OpenURI::Meta) && io.is_a?(Tempfile) @@ -132,88 +135,23 @@ end tempfile.open tempfile end - class ChunkedIO - attr_reader :tempfile - - def initialize(options) - @size = options.fetch(:size) - @chunks = options.fetch(:chunks) - @on_close = options.fetch(:on_close, ->{}) - @tempfile = Tempfile.new("down", binmode: true) + module DownloadedFile + def original_filename + filename_from_content_disposition || filename_from_uri end - def size - @size - end - - def read(length = nil, outbuf = nil) - download_chunk until enough_downloaded?(length) || download_finished? - @tempfile.read(length, outbuf) - end - - def each_chunk - return enum_for(__method__) if !block_given? - yield download_chunk until download_finished? - end - - def eof? - @tempfile.eof? && download_finished? - end - - def rewind - @tempfile.rewind - end - - def close - terminate_download - @tempfile.close! - end - private - def download_chunk - chunk = @chunks.next - write(chunk) - begin - @chunks.peek - rescue StopIteration - terminate_download - end - chunk + def filename_from_content_disposition + meta["content-disposition"].to_s[/filename="([^"]+)"/, 1] end - def enough_downloaded?(length) - length && (@tempfile.pos + length <= @tempfile.size) - end - - def download_finished? - !@on_close - end - - def terminate_download - if @on_close - @on_close.call - @on_close = nil - end - end - - def write(chunk) - current_pos = @tempfile.pos - @tempfile.pos = @tempfile.size - @tempfile.write(chunk) - @tempfile.pos = current_pos - end - end - - module DownloadedFile - def original_filename + def filename_from_uri path = base_uri.path - unless path.empty? || path == "/" - filename = path.split("/").last - CGI.unescape(filename) - end + filename = path.split("/").last + CGI.unescape(filename) if filename end end end