aws-sdk-s3 1.79.1 → 1.212.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1548 -0
- data/LICENSE.txt +202 -0
- data/VERSION +1 -0
- data/lib/aws-sdk-s3/access_grants_credentials.rb +57 -0
- data/lib/aws-sdk-s3/access_grants_credentials_provider.rb +250 -0
- data/lib/aws-sdk-s3/bucket.rb +900 -98
- data/lib/aws-sdk-s3/bucket_acl.rb +44 -10
- data/lib/aws-sdk-s3/bucket_cors.rb +51 -11
- data/lib/aws-sdk-s3/bucket_lifecycle.rb +53 -8
- data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +107 -9
- data/lib/aws-sdk-s3/bucket_logging.rb +43 -6
- data/lib/aws-sdk-s3/bucket_notification.rb +32 -9
- data/lib/aws-sdk-s3/bucket_policy.rb +90 -6
- data/lib/aws-sdk-s3/bucket_region_cache.rb +9 -5
- data/lib/aws-sdk-s3/bucket_request_payment.rb +38 -8
- data/lib/aws-sdk-s3/bucket_tagging.rb +46 -7
- data/lib/aws-sdk-s3/bucket_versioning.rb +127 -9
- data/lib/aws-sdk-s3/bucket_website.rb +46 -7
- data/lib/aws-sdk-s3/client.rb +13729 -3146
- data/lib/aws-sdk-s3/client_api.rb +1604 -277
- data/lib/aws-sdk-s3/customizations/bucket.rb +31 -47
- data/lib/aws-sdk-s3/customizations/errors.rb +40 -0
- data/lib/aws-sdk-s3/customizations/object.rb +253 -82
- data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
- data/lib/aws-sdk-s3/customizations/object_version.rb +13 -0
- data/lib/aws-sdk-s3/customizations/types/permanent_redirect.rb +26 -0
- data/lib/aws-sdk-s3/customizations.rb +28 -29
- data/lib/aws-sdk-s3/default_executor.rb +103 -0
- data/lib/aws-sdk-s3/encryption/client.rb +9 -5
- data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +0 -4
- data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +2 -0
- data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +2 -0
- data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +15 -9
- data/lib/aws-sdk-s3/encryptionV2/client.rb +105 -26
- data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +7 -165
- data/lib/aws-sdk-s3/encryptionV2/decryption.rb +205 -0
- data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +20 -3
- data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +2 -4
- data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +2 -0
- data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +18 -6
- data/lib/aws-sdk-s3/encryptionV2/utils.rb +5 -0
- data/lib/aws-sdk-s3/encryptionV3/client.rb +885 -0
- data/lib/aws-sdk-s3/encryptionV3/decrypt_handler.rb +98 -0
- data/lib/aws-sdk-s3/encryptionV3/decryption.rb +244 -0
- data/lib/aws-sdk-s3/encryptionV3/default_cipher_provider.rb +159 -0
- data/lib/aws-sdk-s3/encryptionV3/default_key_provider.rb +35 -0
- data/lib/aws-sdk-s3/encryptionV3/encrypt_handler.rb +98 -0
- data/lib/aws-sdk-s3/encryptionV3/errors.rb +47 -0
- data/lib/aws-sdk-s3/encryptionV3/io_auth_decrypter.rb +60 -0
- data/lib/aws-sdk-s3/encryptionV3/io_decrypter.rb +35 -0
- data/lib/aws-sdk-s3/encryptionV3/io_encrypter.rb +84 -0
- data/lib/aws-sdk-s3/encryptionV3/key_provider.rb +28 -0
- data/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb +159 -0
- data/lib/aws-sdk-s3/encryptionV3/materials.rb +58 -0
- data/lib/aws-sdk-s3/encryptionV3/utils.rb +321 -0
- data/lib/aws-sdk-s3/encryption_v2.rb +1 -0
- data/lib/aws-sdk-s3/encryption_v3.rb +24 -0
- data/lib/aws-sdk-s3/endpoint_parameters.rb +181 -0
- data/lib/aws-sdk-s3/endpoint_provider.rb +889 -0
- data/lib/aws-sdk-s3/endpoints.rb +1544 -0
- data/lib/aws-sdk-s3/errors.rb +80 -1
- data/lib/aws-sdk-s3/event_streams.rb +1 -1
- data/lib/aws-sdk-s3/express_credentials.rb +55 -0
- data/lib/aws-sdk-s3/express_credentials_provider.rb +59 -0
- data/lib/aws-sdk-s3/file_downloader.rb +258 -82
- data/lib/aws-sdk-s3/file_uploader.rb +25 -14
- data/lib/aws-sdk-s3/legacy_signer.rb +17 -26
- data/lib/aws-sdk-s3/multipart_download_error.rb +8 -0
- data/lib/aws-sdk-s3/multipart_file_uploader.rb +111 -86
- data/lib/aws-sdk-s3/multipart_stream_uploader.rb +110 -92
- data/lib/aws-sdk-s3/multipart_upload.rb +304 -14
- data/lib/aws-sdk-s3/multipart_upload_error.rb +3 -4
- data/lib/aws-sdk-s3/multipart_upload_part.rb +344 -20
- data/lib/aws-sdk-s3/object.rb +2457 -225
- data/lib/aws-sdk-s3/object_acl.rb +76 -15
- data/lib/aws-sdk-s3/object_copier.rb +7 -5
- data/lib/aws-sdk-s3/object_multipart_copier.rb +48 -23
- data/lib/aws-sdk-s3/object_summary.rb +2033 -169
- data/lib/aws-sdk-s3/object_version.rb +470 -53
- data/lib/aws-sdk-s3/plugins/accelerate.rb +1 -39
- data/lib/aws-sdk-s3/plugins/access_grants.rb +178 -0
- data/lib/aws-sdk-s3/plugins/arn.rb +70 -0
- data/lib/aws-sdk-s3/plugins/bucket_dns.rb +3 -41
- data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +1 -6
- data/lib/aws-sdk-s3/plugins/checksum_algorithm.rb +44 -0
- data/lib/aws-sdk-s3/plugins/dualstack.rb +2 -49
- data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
- data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +3 -1
- data/lib/aws-sdk-s3/plugins/express_session_auth.rb +88 -0
- data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +1 -1
- data/lib/aws-sdk-s3/plugins/http_200_errors.rb +87 -26
- data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +8 -26
- data/lib/aws-sdk-s3/plugins/location_constraint.rb +3 -1
- data/lib/aws-sdk-s3/plugins/md5s.rb +10 -68
- data/lib/aws-sdk-s3/plugins/s3_signer.rb +48 -88
- data/lib/aws-sdk-s3/plugins/streaming_retry.rb +28 -9
- data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -1
- data/lib/aws-sdk-s3/presigned_post.rb +99 -78
- data/lib/aws-sdk-s3/presigner.rb +50 -42
- data/lib/aws-sdk-s3/resource.rb +144 -15
- data/lib/aws-sdk-s3/transfer_manager.rb +321 -0
- data/lib/aws-sdk-s3/types.rb +12223 -4723
- data/lib/aws-sdk-s3/waiters.rb +1 -1
- data/lib/aws-sdk-s3.rb +37 -28
- data/sig/bucket.rbs +231 -0
- data/sig/bucket_acl.rbs +78 -0
- data/sig/bucket_cors.rbs +69 -0
- data/sig/bucket_lifecycle.rbs +88 -0
- data/sig/bucket_lifecycle_configuration.rbs +115 -0
- data/sig/bucket_logging.rbs +76 -0
- data/sig/bucket_notification.rbs +114 -0
- data/sig/bucket_policy.rbs +59 -0
- data/sig/bucket_request_payment.rbs +54 -0
- data/sig/bucket_tagging.rbs +65 -0
- data/sig/bucket_versioning.rbs +77 -0
- data/sig/bucket_website.rbs +93 -0
- data/sig/client.rbs +2612 -0
- data/sig/customizations/bucket.rbs +19 -0
- data/sig/customizations/object.rbs +38 -0
- data/sig/customizations/object_summary.rbs +35 -0
- data/sig/errors.rbs +44 -0
- data/sig/multipart_upload.rbs +120 -0
- data/sig/multipart_upload_part.rbs +109 -0
- data/sig/object.rbs +464 -0
- data/sig/object_acl.rbs +86 -0
- data/sig/object_summary.rbs +347 -0
- data/sig/object_version.rbs +143 -0
- data/sig/resource.rbs +141 -0
- data/sig/types.rbs +2899 -0
- data/sig/waiters.rbs +95 -0
- metadata +74 -16
- data/lib/aws-sdk-s3/plugins/bucket_arn.rb +0 -212
|
@@ -7,23 +7,22 @@ module Aws
|
|
|
7
7
|
# @api private
|
|
8
8
|
class FileUploader
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
DEFAULT_MULTIPART_THRESHOLD = 100 * 1024 * 1024
|
|
11
11
|
|
|
12
12
|
# @param [Hash] options
|
|
13
13
|
# @option options [Client] :client
|
|
14
|
-
# @option options [Integer] :multipart_threshold (
|
|
14
|
+
# @option options [Integer] :multipart_threshold (104857600)
|
|
15
15
|
def initialize(options = {})
|
|
16
|
-
@options = options
|
|
17
16
|
@client = options[:client] || Client.new
|
|
18
|
-
@
|
|
19
|
-
|
|
17
|
+
@executor = options[:executor]
|
|
18
|
+
@http_chunk_size = options[:http_chunk_size]
|
|
19
|
+
@multipart_threshold = options[:multipart_threshold] || DEFAULT_MULTIPART_THRESHOLD
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# @return [Client]
|
|
23
23
|
attr_reader :client
|
|
24
24
|
|
|
25
|
-
# @return [Integer] Files larger than this in bytes are uploaded
|
|
26
|
-
# using a {MultipartFileUploader}.
|
|
25
|
+
# @return [Integer] Files larger than or equal to this in bytes are uploaded using a {MultipartFileUploader}.
|
|
27
26
|
attr_reader :multipart_threshold
|
|
28
27
|
|
|
29
28
|
# @param [String, Pathname, File, Tempfile] source The file to upload.
|
|
@@ -32,20 +31,29 @@ module Aws
|
|
|
32
31
|
# @option options [Proc] :progress_callback
|
|
33
32
|
# A Proc that will be called when each chunk of the upload is sent.
|
|
34
33
|
# It will be invoked with [bytes_read], [total_sizes]
|
|
34
|
+
# @option options [Integer] :thread_count
|
|
35
|
+
# The thread count to use for multipart uploads. Ignored for
|
|
36
|
+
# objects smaller than the multipart threshold.
|
|
35
37
|
# @return [void]
|
|
36
38
|
def upload(source, options = {})
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
Aws::Plugins::UserAgent.metric('S3_TRANSFER') do
|
|
40
|
+
if File.size(source) >= @multipart_threshold
|
|
41
|
+
MultipartFileUploader.new(
|
|
42
|
+
client: @client,
|
|
43
|
+
executor: @executor,
|
|
44
|
+
http_chunk_size: @http_chunk_size
|
|
45
|
+
).upload(source, options)
|
|
46
|
+
else
|
|
47
|
+
put_object(source, options)
|
|
48
|
+
end
|
|
41
49
|
end
|
|
42
50
|
end
|
|
43
51
|
|
|
44
52
|
private
|
|
45
53
|
|
|
46
|
-
def open_file(source)
|
|
47
|
-
if String
|
|
48
|
-
File.open(source, 'rb'
|
|
54
|
+
def open_file(source, &block)
|
|
55
|
+
if source.is_a?(String) || source.is_a?(Pathname)
|
|
56
|
+
File.open(source, 'rb', &block)
|
|
49
57
|
else
|
|
50
58
|
yield(source)
|
|
51
59
|
end
|
|
@@ -56,7 +64,10 @@ module Aws
|
|
|
56
64
|
options[:on_chunk_sent] = single_part_progress(callback)
|
|
57
65
|
end
|
|
58
66
|
open_file(source) do |file|
|
|
67
|
+
Thread.current[:net_http_override_body_stream_chunk] = @http_chunk_size if @http_chunk_size
|
|
59
68
|
@client.put_object(options.merge(body: file))
|
|
69
|
+
ensure
|
|
70
|
+
Thread.current[:net_http_override_body_stream_chunk] = nil
|
|
60
71
|
end
|
|
61
72
|
end
|
|
62
73
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
require 'set'
|
|
4
4
|
require 'time'
|
|
5
5
|
require 'openssl'
|
|
6
|
-
require
|
|
7
|
-
require
|
|
6
|
+
require "cgi/escape"
|
|
7
|
+
require "cgi/util" if RUBY_VERSION < "3.5"
|
|
8
8
|
require 'aws-sdk-core/query'
|
|
9
9
|
|
|
10
10
|
module Aws
|
|
@@ -157,33 +157,24 @@ module Aws
|
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
def uri_escape(s)
|
|
160
|
-
|
|
161
160
|
#URI.escape(s)
|
|
162
161
|
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
#
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
# (
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
#
|
|
174
|
-
#
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
|
|
178
|
-
# URI.escape(s),
|
|
179
|
-
# ]
|
|
180
|
-
# next if e.uniq.length == 1
|
|
181
|
-
# puts("%5s %5s %5s %5s %5s %5s %5s" % ([s.inspect] + e))
|
|
182
|
-
# }
|
|
183
|
-
#
|
|
184
|
-
WEBrick::HTTPUtils.escape(s).gsub('%5B', '[').gsub('%5D', ']')
|
|
162
|
+
# (0..255).each {|c|
|
|
163
|
+
# s = [c].pack("C")
|
|
164
|
+
# e = [
|
|
165
|
+
# CGI.escape(s),
|
|
166
|
+
# ERB::Util.url_encode(s),
|
|
167
|
+
# URI.encode_www_form_component(s),
|
|
168
|
+
# WEBrick::HTTPUtils.escape_form(s),
|
|
169
|
+
# WEBrick::HTTPUtils.escape(s),
|
|
170
|
+
# URI.escape(s),
|
|
171
|
+
# URI::DEFAULT_PARSER.escape(s)
|
|
172
|
+
# ]
|
|
173
|
+
# next if e.uniq.length == 1
|
|
174
|
+
# puts("%5s %5s %5s %5s %5s %5s %5s %5s" % ([s.inspect] + e))
|
|
175
|
+
# }
|
|
176
|
+
URI::DEFAULT_PARSER.escape(s)
|
|
185
177
|
end
|
|
186
|
-
|
|
187
178
|
end
|
|
188
179
|
end
|
|
189
180
|
end
|
|
@@ -7,30 +7,22 @@ module Aws
|
|
|
7
7
|
module S3
|
|
8
8
|
# @api private
|
|
9
9
|
class MultipartFileUploader
|
|
10
|
-
|
|
11
10
|
MIN_PART_SIZE = 5 * 1024 * 1024 # 5MB
|
|
12
|
-
|
|
13
|
-
FILE_TOO_SMALL = "unable to multipart upload files smaller than 5MB"
|
|
14
|
-
|
|
15
11
|
MAX_PARTS = 10_000
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# @api private
|
|
25
|
-
UPLOAD_PART_OPTIONS = Set.new(
|
|
26
|
-
Client.api.operation(:upload_part).input.shape.member_names
|
|
12
|
+
CREATE_OPTIONS = Set.new(Client.api.operation(:create_multipart_upload).input.shape.member_names)
|
|
13
|
+
COMPLETE_OPTIONS = Set.new(Client.api.operation(:complete_multipart_upload).input.shape.member_names)
|
|
14
|
+
UPLOAD_PART_OPTIONS = Set.new(Client.api.operation(:upload_part).input.shape.member_names)
|
|
15
|
+
CHECKSUM_KEYS = Set.new(
|
|
16
|
+
Client.api.operation(:upload_part).input.shape.members.map do |n, s|
|
|
17
|
+
n if s.location == 'header' && s.location_name.start_with?('x-amz-checksum-')
|
|
18
|
+
end.compact
|
|
27
19
|
)
|
|
28
20
|
|
|
29
21
|
# @option options [Client] :client
|
|
30
|
-
# @option options [Integer] :thread_count (THREAD_COUNT)
|
|
31
22
|
def initialize(options = {})
|
|
32
23
|
@client = options[:client] || Client.new
|
|
33
|
-
@
|
|
24
|
+
@executor = options[:executor]
|
|
25
|
+
@http_chunk_size = options[:http_chunk_size]
|
|
34
26
|
end
|
|
35
27
|
|
|
36
28
|
# @return [Client]
|
|
@@ -42,15 +34,14 @@ module Aws
|
|
|
42
34
|
# @option options [Proc] :progress_callback
|
|
43
35
|
# A Proc that will be called when each chunk of the upload is sent.
|
|
44
36
|
# It will be invoked with [bytes_read], [total_sizes]
|
|
45
|
-
# @return [
|
|
37
|
+
# @return [Seahorse::Client::Response] - the CompleteMultipartUploadResponse
|
|
46
38
|
def upload(source, options = {})
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
end
|
|
39
|
+
file_size = File.size(source)
|
|
40
|
+
raise ArgumentError, 'unable to multipart upload files smaller than 5MB' if file_size < MIN_PART_SIZE
|
|
41
|
+
|
|
42
|
+
upload_id = initiate_upload(options)
|
|
43
|
+
parts = upload_parts(upload_id, source, file_size, options)
|
|
44
|
+
complete_upload(upload_id, parts, file_size, options)
|
|
54
45
|
end
|
|
55
46
|
|
|
56
47
|
private
|
|
@@ -59,19 +50,21 @@ module Aws
|
|
|
59
50
|
@client.create_multipart_upload(create_opts(options)).upload_id
|
|
60
51
|
end
|
|
61
52
|
|
|
62
|
-
def complete_upload(upload_id, parts, options)
|
|
53
|
+
def complete_upload(upload_id, parts, file_size, options)
|
|
63
54
|
@client.complete_multipart_upload(
|
|
64
|
-
|
|
65
|
-
key: options[:key],
|
|
55
|
+
**complete_opts(options),
|
|
66
56
|
upload_id: upload_id,
|
|
67
|
-
multipart_upload: { parts: parts }
|
|
57
|
+
multipart_upload: { parts: parts },
|
|
58
|
+
mpu_object_size: file_size
|
|
68
59
|
)
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
abort_upload(upload_id, options, [e])
|
|
69
62
|
end
|
|
70
63
|
|
|
71
|
-
def upload_parts(upload_id, source, options)
|
|
72
|
-
pending = PartList.new(compute_parts(upload_id, source, options))
|
|
64
|
+
def upload_parts(upload_id, source, file_size, options)
|
|
73
65
|
completed = PartList.new
|
|
74
|
-
|
|
66
|
+
pending = PartList.new(compute_parts(upload_id, source, file_size, options))
|
|
67
|
+
errors = upload_with_executor(pending, completed, options)
|
|
75
68
|
if errors.empty?
|
|
76
69
|
completed.to_a.sort_by { |part| part[:part_number] }
|
|
77
70
|
else
|
|
@@ -80,34 +73,30 @@ module Aws
|
|
|
80
73
|
end
|
|
81
74
|
|
|
82
75
|
def abort_upload(upload_id, options, errors)
|
|
83
|
-
@client.abort_multipart_upload(
|
|
84
|
-
|
|
85
|
-
key: options[:key],
|
|
86
|
-
upload_id: upload_id
|
|
87
|
-
)
|
|
88
|
-
msg = "multipart upload failed: #{errors.map(&:message).join("; ")}"
|
|
76
|
+
@client.abort_multipart_upload(bucket: options[:bucket], key: options[:key], upload_id: upload_id)
|
|
77
|
+
msg = "multipart upload failed: #{errors.map(&:message).join('; ')}"
|
|
89
78
|
raise MultipartUploadError.new(msg, errors)
|
|
90
|
-
rescue MultipartUploadError =>
|
|
91
|
-
raise
|
|
92
|
-
rescue =>
|
|
93
|
-
msg = "failed to abort multipart upload: #{
|
|
94
|
-
|
|
79
|
+
rescue MultipartUploadError => e
|
|
80
|
+
raise e
|
|
81
|
+
rescue StandardError => e
|
|
82
|
+
msg = "failed to abort multipart upload: #{e&.message}. " \
|
|
83
|
+
"Multipart upload failed: #{errors.map(&:message).join('; ')}"
|
|
84
|
+
raise MultipartUploadError.new(msg, errors + [e])
|
|
95
85
|
end
|
|
96
86
|
|
|
97
|
-
def compute_parts(upload_id, source, options)
|
|
98
|
-
|
|
99
|
-
default_part_size = compute_default_part_size(size)
|
|
87
|
+
def compute_parts(upload_id, source, file_size, options)
|
|
88
|
+
default_part_size = compute_default_part_size(file_size)
|
|
100
89
|
offset = 0
|
|
101
90
|
part_number = 1
|
|
102
91
|
parts = []
|
|
103
|
-
while offset <
|
|
92
|
+
while offset < file_size
|
|
104
93
|
parts << upload_part_opts(options).merge(
|
|
105
94
|
upload_id: upload_id,
|
|
106
95
|
part_number: part_number,
|
|
107
96
|
body: FilePart.new(
|
|
108
97
|
source: source,
|
|
109
98
|
offset: offset,
|
|
110
|
-
size: part_size(
|
|
99
|
+
size: part_size(file_size, default_part_size, offset)
|
|
111
100
|
)
|
|
112
101
|
)
|
|
113
102
|
part_number += 1
|
|
@@ -116,54 +105,81 @@ module Aws
|
|
|
116
105
|
parts
|
|
117
106
|
end
|
|
118
107
|
|
|
108
|
+
def checksum_key?(key)
|
|
109
|
+
CHECKSUM_KEYS.include?(key)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def has_checksum_key?(keys)
|
|
113
|
+
keys.any? { |key| checksum_key?(key) }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def checksum_not_required?(options)
|
|
117
|
+
@client.config.request_checksum_calculation == 'when_required' && !options[:checksum_algorithm]
|
|
118
|
+
end
|
|
119
|
+
|
|
119
120
|
def create_opts(options)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
opts = {}
|
|
122
|
+
unless checksum_not_required?(options)
|
|
123
|
+
opts[:checksum_algorithm] = Aws::Plugins::ChecksumAlgorithm::DEFAULT_CHECKSUM
|
|
123
124
|
end
|
|
125
|
+
opts[:checksum_type] = 'FULL_OBJECT' if has_checksum_key?(options.keys)
|
|
126
|
+
CREATE_OPTIONS.each_with_object(opts) { |k, h| h[k] = options[k] if options.key?(k) }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def complete_opts(options)
|
|
130
|
+
opts = {}
|
|
131
|
+
opts[:checksum_type] = 'FULL_OBJECT' if has_checksum_key?(options.keys)
|
|
132
|
+
COMPLETE_OPTIONS.each_with_object(opts) { |k, h| h[k] = options[k] if options.key?(k) }
|
|
124
133
|
end
|
|
125
134
|
|
|
126
135
|
def upload_part_opts(options)
|
|
127
|
-
UPLOAD_PART_OPTIONS.
|
|
128
|
-
|
|
129
|
-
hash
|
|
136
|
+
UPLOAD_PART_OPTIONS.each_with_object({}) do |key, hash|
|
|
137
|
+
# don't pass through checksum calculations
|
|
138
|
+
hash[key] = options[key] if options.key?(key) && !checksum_key?(key)
|
|
130
139
|
end
|
|
131
140
|
end
|
|
132
141
|
|
|
133
|
-
def
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
142
|
+
def upload_with_executor(pending, completed, options)
|
|
143
|
+
upload_attempts = 0
|
|
144
|
+
completion_queue = Queue.new
|
|
145
|
+
abort_upload = false
|
|
146
|
+
errors = []
|
|
147
|
+
progress = MultipartProgress.new(pending, options[:progress_callback])
|
|
148
|
+
|
|
149
|
+
while (part = pending.shift)
|
|
150
|
+
break if abort_upload
|
|
151
|
+
|
|
152
|
+
upload_attempts += 1
|
|
153
|
+
@executor.post(part) do |p|
|
|
154
|
+
Thread.current[:net_http_override_body_stream_chunk] = @http_chunk_size if @http_chunk_size
|
|
155
|
+
update_progress(progress, p)
|
|
156
|
+
resp = @client.upload_part(p)
|
|
157
|
+
p[:body].close
|
|
158
|
+
completed_part = { etag: resp.etag, part_number: p[:part_number] }
|
|
159
|
+
apply_part_checksum(resp, completed_part)
|
|
160
|
+
completed.push(completed_part)
|
|
161
|
+
rescue StandardError => e
|
|
162
|
+
abort_upload = true
|
|
163
|
+
errors << e
|
|
164
|
+
ensure
|
|
165
|
+
Thread.current[:net_http_override_body_stream_chunk] = nil if @http_chunk_size
|
|
166
|
+
completion_queue << :done
|
|
158
167
|
end
|
|
159
|
-
thread.abort_on_exception = true
|
|
160
|
-
threads << thread
|
|
161
168
|
end
|
|
162
|
-
|
|
169
|
+
|
|
170
|
+
upload_attempts.times { completion_queue.pop }
|
|
171
|
+
errors
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def apply_part_checksum(resp, part)
|
|
175
|
+
return unless (checksum = resp.context.params[:checksum_algorithm])
|
|
176
|
+
|
|
177
|
+
k = :"checksum_#{checksum.downcase}"
|
|
178
|
+
part[k] = resp.send(k)
|
|
163
179
|
end
|
|
164
180
|
|
|
165
|
-
def compute_default_part_size(
|
|
166
|
-
[(
|
|
181
|
+
def compute_default_part_size(file_size)
|
|
182
|
+
[(file_size.to_f / MAX_PARTS).ceil, MIN_PART_SIZE].max.to_i
|
|
167
183
|
end
|
|
168
184
|
|
|
169
185
|
def part_size(total_size, part_size, offset)
|
|
@@ -174,9 +190,17 @@ module Aws
|
|
|
174
190
|
end
|
|
175
191
|
end
|
|
176
192
|
|
|
193
|
+
def update_progress(progress, part)
|
|
194
|
+
return unless progress.progress_callback
|
|
195
|
+
|
|
196
|
+
part[:on_chunk_sent] =
|
|
197
|
+
proc do |_chunk, bytes, _total|
|
|
198
|
+
progress.call(part[:part_number], bytes)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
177
202
|
# @api private
|
|
178
203
|
class PartList
|
|
179
|
-
|
|
180
204
|
def initialize(parts = [])
|
|
181
205
|
@parts = parts
|
|
182
206
|
@mutex = Mutex.new
|
|
@@ -205,7 +229,6 @@ module Aws
|
|
|
205
229
|
def to_a
|
|
206
230
|
@mutex.synchronize { @parts.dup }
|
|
207
231
|
end
|
|
208
|
-
|
|
209
232
|
end
|
|
210
233
|
|
|
211
234
|
# @api private
|
|
@@ -216,6 +239,8 @@ module Aws
|
|
|
216
239
|
@progress_callback = progress_callback
|
|
217
240
|
end
|
|
218
241
|
|
|
242
|
+
attr_reader :progress_callback
|
|
243
|
+
|
|
219
244
|
def call(part_number, bytes_read)
|
|
220
245
|
# part numbers start at 1
|
|
221
246
|
@bytes_sent[part_number - 1] = bytes_read
|