File: file_uploader.rb

package info (click to toggle)
ruby-aws-sdk-s3 1.170.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,740 kB
  • sloc: ruby: 16,388; makefile: 3
file content (77 lines) | stat: -rw-r--r-- 2,499 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# frozen_string_literal: true

require 'pathname'

module Aws
  module S3
    # @api private
    class FileUploader

      ONE_HUNDRED_MEGABYTES = 100 * 1024 * 1024

      # @param [Hash] options
      # @option options [Client] :client
      # @option options [Integer] :multipart_threshold (104857600)
      def initialize(options = {})
        @options = options
        @client = options[:client] || Client.new
        @multipart_threshold = options[:multipart_threshold] ||
                               ONE_HUNDRED_MEGABYTES
      end

      # @return [Client]
      attr_reader :client

      # @return [Integer] Files larger than or equal to this in bytes are uploaded
      #   using a {MultipartFileUploader}.
      attr_reader :multipart_threshold

      # @param [String, Pathname, File, Tempfile] source The file to upload.
      # @option options [required, String] :bucket The bucket to upload to.
      # @option options [required, String] :key The key for the object.
      # @option options [Proc] :progress_callback
      #   A Proc that will be called when each chunk of the upload is sent.
      #   It will be invoked with [bytes_read], [total_sizes]
      # @option options [Integer] :thread_count
      #   The thread count to use for multipart uploads. Ignored for
      #   objects smaller than the multipart threshold.
      # @return [void]
      def upload(source, options = {})
        Aws::Plugins::UserAgent.metric('S3_TRANSFER') do
          if File.size(source) >= multipart_threshold
            MultipartFileUploader.new(@options).upload(source, options)
          else
            # remove multipart parameters not supported by put_object
            options.delete(:thread_count)
            put_object(source, options)
          end
        end
      end

      private

      def open_file(source)
        if String === source || Pathname === source
          File.open(source, 'rb') { |file| yield(file) }
        else
          yield(source)
        end
      end

      def put_object(source, options)
        if (callback = options.delete(:progress_callback))
          options[:on_chunk_sent] = single_part_progress(callback)
        end
        open_file(source) do |file|
          @client.put_object(options.merge(body: file))
        end
      end

      def single_part_progress(progress_callback)
        proc do |_chunk, bytes_read, total_size|
          progress_callback.call([bytes_read], [total_size])
        end
      end
    end
  end
end