aws-sdk-s3 1.211.0 → 1.217.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.
@@ -287,10 +287,10 @@ module Aws::S3
287
287
  # Confirms that the requester knows that they will be charged for the
288
288
  # request. Bucket owners need not specify this parameter in their
289
289
  # requests. If either the source or destination S3 bucket has Requester
290
- # Pays enabled, the requester will pay for corresponding charges to copy
291
- # the object. For information about downloading objects from Requester
292
- # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
293
- # in the *Amazon S3 User Guide*.
290
+ # Pays enabled, the requester will pay for the corresponding charges.
291
+ # For information about downloading objects from Requester Pays buckets,
292
+ # see [Downloading Objects in Requester Pays Buckets][1] in the *Amazon
293
+ # S3 User Guide*.
294
294
  #
295
295
  # <note markdown="1"> This functionality is not supported for directory buckets.
296
296
  #
@@ -553,10 +553,10 @@ module Aws::S3
553
553
  # Confirms that the requester knows that they will be charged for the
554
554
  # request. Bucket owners need not specify this parameter in their
555
555
  # requests. If either the source or destination S3 bucket has Requester
556
- # Pays enabled, the requester will pay for corresponding charges to copy
557
- # the object. For information about downloading objects from Requester
558
- # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
559
- # in the *Amazon S3 User Guide*.
556
+ # Pays enabled, the requester will pay for the corresponding charges.
557
+ # For information about downloading objects from Requester Pays buckets,
558
+ # see [Downloading Objects in Requester Pays Buckets][1] in the *Amazon
559
+ # S3 User Guide*.
560
560
  #
561
561
  # <note markdown="1"> This functionality is not supported for directory buckets.
562
562
  #
@@ -730,10 +730,10 @@ module Aws::S3
730
730
  # Confirms that the requester knows that they will be charged for the
731
731
  # request. Bucket owners need not specify this parameter in their
732
732
  # requests. If either the source or destination S3 bucket has Requester
733
- # Pays enabled, the requester will pay for corresponding charges to copy
734
- # the object. For information about downloading objects from Requester
735
- # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
736
- # in the *Amazon S3 User Guide*.
733
+ # Pays enabled, the requester will pay for the corresponding charges.
734
+ # For information about downloading objects from Requester Pays buckets,
735
+ # see [Downloading Objects in Requester Pays Buckets][1] in the *Amazon
736
+ # S3 User Guide*.
737
737
  #
738
738
  # <note markdown="1"> This functionality is not supported for directory buckets.
739
739
  #
@@ -878,10 +878,10 @@ module Aws::S3
878
878
  # Confirms that the requester knows that they will be charged for the
879
879
  # request. Bucket owners need not specify this parameter in their
880
880
  # requests. If either the source or destination S3 bucket has Requester
881
- # Pays enabled, the requester will pay for corresponding charges to copy
882
- # the object. For information about downloading objects from Requester
883
- # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
884
- # in the *Amazon S3 User Guide*.
881
+ # Pays enabled, the requester will pay for the corresponding charges.
882
+ # For information about downloading objects from Requester Pays buckets,
883
+ # see [Downloading Objects in Requester Pays Buckets][1] in the *Amazon
884
+ # S3 User Guide*.
885
885
  #
886
886
  # <note markdown="1"> This functionality is not supported for directory buckets.
887
887
  #
@@ -64,6 +64,7 @@ module Aws::S3
64
64
  # grant_write_acp: "GrantWriteACP",
65
65
  # object_lock_enabled_for_bucket: false,
66
66
  # object_ownership: "BucketOwnerPreferred", # accepts BucketOwnerPreferred, ObjectWriter, BucketOwnerEnforced
67
+ # bucket_namespace: "account-regional", # accepts account-regional, global
67
68
  # })
68
69
  # @param [Hash] options ({})
69
70
  # @option options [String] :acl
@@ -171,6 +172,33 @@ module Aws::S3
171
172
  #
172
173
  #
173
174
  # [1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
175
+ # @option options [String] :bucket_namespace
176
+ # Specifies the namespace where you want to create your general purpose
177
+ # bucket. When you create a general purpose bucket, you can choose to
178
+ # create a bucket in the shared global namespace or you can choose to
179
+ # create a bucket in your account regional namespace. Your account
180
+ # regional namespace is a subdivision of the global namespace that only
181
+ # your account can create buckets in. For more information on bucket
182
+ # namespaces, see [Namespaces for general purpose buckets][1].
183
+ #
184
+ # General purpose buckets in your account regional namespace must follow
185
+ # a specific naming convention. These buckets consist of a bucket name
186
+ # prefix that you create, and a suffix that contains your 12-digit
187
+ # Amazon Web Services Account ID, the Amazon Web Services Region code,
188
+ # and ends with `-an`. Bucket names must follow the format
189
+ # `bucket-name-prefix-accountId-region-an` (for example,
190
+ # `amzn-s3-demo-bucket-111122223333-us-west-2-an`). For information
191
+ # about bucket naming restrictions, see [Account regional namespace
192
+ # naming rules][2] in the *Amazon S3 User Guide*.
193
+ #
194
+ # <note markdown="1"> This functionality is not supported for directory buckets.
195
+ #
196
+ # </note>
197
+ #
198
+ #
199
+ #
200
+ # [1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/gpbucketnamespaces.html
201
+ # [2]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html#account-regional-naming-rules
174
202
  # @return [Bucket]
175
203
  def create_bucket(options = {})
176
204
  Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
@@ -7,7 +7,9 @@ module Aws
7
7
  #
8
8
  # * upload a file with multipart upload
9
9
  # * upload a stream with multipart upload
10
- # * download a S3 object with multipart download
10
+ # * upload all files in a directory to an S3 bucket recursively or non-recursively
11
+ # * download an S3 object with multipart download
12
+ # * download all objects in an S3 bucket with same prefix to a local directory
11
13
  # * track transfer progress by using progress listener
12
14
  #
13
15
  # ## Executor Management
@@ -49,19 +51,21 @@ module Aws
49
51
  # executor.shutdown # You must shutdown custom executors
50
52
  #
51
53
  class TransferManager
52
-
53
54
  # @param [Hash] options
54
55
  # @option options [S3::Client] :client (S3::Client.new)
55
56
  # The S3 client to use for {TransferManager} operations. If not provided, a new default client
56
57
  # will be created automatically.
57
- # @option options [Object] :executor
58
+ # @option options [Object] :executor (nil)
58
59
  # The executor to use for multipart operations. Must implement the same interface as {DefaultExecutor}.
59
60
  # If not provided, a new {DefaultExecutor} will be created automatically for each operation and
60
61
  # shutdown after completion. When provided a custom executor, it will be reused across operations, and
61
62
  # you are responsible for shutting it down when finished.
63
+ # @option options [Logger] :logger (nil)
64
+ # The Logger instance for logging transfer operations. If not set, logging is disabled.
62
65
  def initialize(options = {})
63
66
  @client = options[:client] || Client.new
64
67
  @executor = options[:executor]
68
+ @logger = options[:logger]
65
69
  end
66
70
 
67
71
  # @return [S3::Client]
@@ -70,6 +74,100 @@ module Aws
70
74
  # @return [Object]
71
75
  attr_reader :executor
72
76
 
77
+ # @return [Logger]
78
+ attr_reader :logger
79
+
80
+ # Downloads objects in a S3 bucket to a local directory.
81
+ #
82
+ # The downloaded directory structure will match the provided S3 virtual bucket. For example,
83
+ # assume that you have the following keys in your bucket:
84
+ #
85
+ # * sample.jpg
86
+ # * photos/2022/January/sample.jpg
87
+ # * photos/2022/February/sample1.jpg
88
+ # * photos/2022/February/sample2.jpg
89
+ # * photos/2022/February/sample3.jpg
90
+ #
91
+ # Given a request to download bucket to a destination with path of `/test`, the downloaded
92
+ # directory would look like this:
93
+ #
94
+ # ```
95
+ # |- test
96
+ # |- sample.jpg
97
+ # |- photos
98
+ # |- 2022
99
+ # |- January
100
+ # |- sample.jpg
101
+ # |- February
102
+ # |- sample1.jpg
103
+ # |- sample2.jpg
104
+ # |- sample3.jpg
105
+ # ```
106
+ #
107
+ # Directory markers (zero-byte objects ending with `/`) are skipped during download.
108
+ # Existing files with same name as downloaded objects will be overwritten.
109
+ #
110
+ # Object keys containing path traversal sequences (`..` or `.`) will raise an error.
111
+ #
112
+ # @example Downloading buckets to a local directory
113
+ # tm = TransferManager.new
114
+ # tm.download_directory('/local/path', bucket: 'my-bucket')
115
+ # # => {completed_downloads: 7, failed_downloads: 0, errors: 0}
116
+ #
117
+ # @param [String] destination
118
+ # The location directory path to download objects to. Created if it doesn't exist.
119
+ # If files with the same names already exist in the destination, they will be overwritten.
120
+ #
121
+ # @param [String] bucket
122
+ # The name of the bucket to download from.
123
+ #
124
+ # @param [Hash] options
125
+ #
126
+ # @option options [String] :s3_prefix (nil)
127
+ # Limit the download to objects that begin with the specified prefix. The prefix is
128
+ # passed directly to the S3 ListObjectsV2 API for filtering. To match only objects
129
+ # within a specific "folder", include a trailing `/` (e.g., `"photos/"` instead of
130
+ # `"photos"`). The full object key is preserved in the local file path.
131
+ #
132
+ # @option options [Boolean] :ignore_failure (false)
133
+ # How to handle individual file download failures:
134
+ # * `false` (default) - Cancel all ongoing requests, terminate the ongoing downloads and raise an exception
135
+ # * `true` - Continue downloading remaining objects, report failures in result.
136
+ #
137
+ # @option options [Proc] :filter_callback (nil)
138
+ # A Proc to filter which objects to download. Called with `(object)` for each object.
139
+ # Return `true` to download the object, `false` to skip it.
140
+ #
141
+ # @option options [Proc] :request_callback (nil)
142
+ # A Proc to modify download parameters for each object. Called with `(key, params)`.
143
+ # Must return the modified parameters.
144
+ #
145
+ # @option options [Integer] :thread_count (10)
146
+ # The number of threads to use for multipart downloads of individual large files.
147
+ # Only used when no custom executor is provided to the {TransferManager}.
148
+ #
149
+ # @note On case-insensitive filesystems (e.g., Windows, macOS default), S3 object keys that
150
+ # differ only by case (e.g., "File.txt" and "file.txt") may overwrite each other when
151
+ # downloaded. This condition is not automatically detected. Use the `:filter_callback`
152
+ # option to handle such conflicts if needed.
153
+ #
154
+ # @raise [DirectoryDownloadError] Raised when download fails with `ignore_failure: false` (default)
155
+ #
156
+ # @return [Hash] Returns a hash with download statistics:
157
+ #
158
+ # * `:completed_downloads` - Number of objects successfully downloaded
159
+ # * `:failed_downloads` - Number of objects that failed to download
160
+ # * `:errors` - Array of errors for failed downloads (only present when failures occur)
161
+ def download_directory(destination, bucket:, **options)
162
+ Aws::Plugins::UserAgent.metric('S3_TRANSFER', 'S3_TRANSFER_DOWNLOAD_DIRECTORY') do
163
+ executor = @executor || DefaultExecutor.new(max_threads: options.delete(:thread_count))
164
+ downloader = DirectoryDownloader.new(client: @client, executor: executor, logger: @logger)
165
+ result = downloader.download(destination, bucket: bucket, **options)
166
+ executor.shutdown unless @executor
167
+ result
168
+ end
169
+ end
170
+
73
171
  # Downloads a file in S3 to a path on disk.
74
172
  #
75
173
  # # small files (< 5MB) are downloaded in a single API call
@@ -120,8 +218,9 @@ module Aws
120
218
  #
121
219
  # @option options [Integer] :chunk_size required in `"get_range"` mode.
122
220
  #
123
- # @option options [Integer] :thread_count (10) Customize threads used in the multipart download.
124
- # Only used when no custom executor is provided (creates {DefaultExecutor} with given thread count).
221
+ # @option options [Integer] :thread_count (10)
222
+ # The number of threads to use for multipart downloads.
223
+ # Only used when no custom executor is provided to the {TransferManager}.
125
224
  #
126
225
  # @option options [String] :checksum_mode ("ENABLED")
127
226
  # This option is deprecated. Use `:response_checksum_validation` on your S3 client instead.
@@ -153,6 +252,122 @@ module Aws
153
252
  true
154
253
  end
155
254
 
255
+ # Uploads all files under the given directory to the provided S3 bucket.
256
+ # The key name transformation depends on the optional prefix.
257
+ #
258
+ # By default, all subdirectories will be uploaded non-recursively and symbolic links are not
259
+ # followed automatically. Assume you have a local directory `/test` with the following structure:
260
+ #
261
+ # ```
262
+ # |- test
263
+ # |- sample.jpg
264
+ # |- photos
265
+ # |- 2022
266
+ # |- January
267
+ # |- sample.jpg
268
+ # |- February
269
+ # |- sample1.jpg
270
+ # |- sample2.jpg
271
+ # |- sample3.jpg
272
+ # ```
273
+ #
274
+ # Give a request to upload directory `/test` to an S3 bucket on default setting, the target bucket will have the
275
+ # following S3 objects:
276
+ #
277
+ # * sample.jpg
278
+ #
279
+ # If `:recursive` set to `true`, the target bucket will have the following S3 buckets:
280
+ #
281
+ # * sample.jpg
282
+ # * photos/2022/January/sample.jpg
283
+ # * photos/2022/February/sample1.jpg
284
+ # * photos/2022/February/sample2.jpg
285
+ # * photos/2022/February/sample3.jpg
286
+ #
287
+ # Only regular files are uploaded; special files (sockets, pipes, devices) are skipped.
288
+ # Symlink cycles are detected and skipped when following symlinks.
289
+ # Empty directories are not represented in S3. Existing S3 objects with the same key are
290
+ # overwritten.
291
+ #
292
+ # @example Uploading a directory
293
+ # tm = TransferManager.new
294
+ # tm.upload_directory('/path/to/directory', bucket: 'bucket')
295
+ # # => {completed_uploads: 7, failed_uploads: 0}
296
+ #
297
+ # @example Using filter callback to upload only text files
298
+ # tm = TransferManager.new
299
+ # filter = proc do |file_path, file_name|
300
+ # File.extname(file_name) == '.txt' # Only upload .txt files
301
+ # end
302
+ # tm.upload_directory('/path/to/directory', bucket: 'bucket', filter_callback: filter)
303
+ #
304
+ # @param [String, Pathname, File, Tempfile] source
305
+ # The source directory to upload.
306
+ #
307
+ # @param [String] bucket
308
+ # The name of the bucket to upload objects to.
309
+ #
310
+ # @param [Hash] options
311
+ #
312
+ # @option options [String] :s3_prefix (nil)
313
+ # The S3 key prefix to use for each object. If not provided, files will be uploaded to the root of the bucket.
314
+ #
315
+ # @option options [Boolean] :recursive (false)
316
+ # Whether to upload directories recursively:
317
+ #
318
+ # * `false` (default) - only files in the top-level directory are uploaded, subdirectories are ignored.
319
+ # * `true` - all files and subdirectories are uploaded recursively.
320
+ #
321
+ # @option options [Boolean] :follow_symlinks (false)
322
+ # Whether to follow symbolic links when traversing the file tree:
323
+ #
324
+ # * `false` (default) - symbolic links are ignored and not uploaded.
325
+ # * `true` - symbolic links are followed and their target files/directories are uploaded. Symlink cycles
326
+ # are detected and skipped.
327
+ #
328
+ # @option options [Boolean] :ignore_failure (false)
329
+ # How to handle individual file upload failures:
330
+ #
331
+ # * `false` (default) - Cancel all ongoing requests, terminate the directory upload, and raise an exception
332
+ # * `true` - Ignore the failure and continue the transfer for other files
333
+ #
334
+ # @option options [Proc] :filter_callback (nil)
335
+ # A Proc to filter which files to upload. Called with `(file_path, file_name)` for each file.
336
+ # Return `true` to upload the file, `false` to skip it.
337
+ #
338
+ # @option options [Proc] :request_callback (nil)
339
+ # A Proc to modify upload parameters for each file. Called with `(file_path, params)`.
340
+ # Must return the modified parameters.
341
+ #
342
+ # @option options [Integer] :http_chunk_size (16384) Size in bytes for each chunk when streaming request bodies
343
+ # over HTTP. Controls the buffer size used when sending data to S3. Larger values may improve throughput by
344
+ # reducing the number of network writes, but use more memory. Custom values must be at least 16KB.
345
+ # Only Ruby MRI is supported.
346
+ #
347
+ # @option options [Integer] :thread_count (10)
348
+ # The number of threads to use for multipart uploads of individual large files.
349
+ # Only used when no custom executor is provided to the {TransferManager}.
350
+ #
351
+ # @raise [DirectoryUploadError] Raised when:
352
+ #
353
+ # * Upload failure with `ignore_failure: false` (default)
354
+ # * Directory traversal failure (permission denied, broken symlink, etc.)
355
+ #
356
+ # @return [Hash] Returns a hash with upload statistics:
357
+ #
358
+ # * `:completed_uploads` - Number of files successfully uploaded
359
+ # * `:failed_uploads` - Number of files that failed to upload
360
+ # * `:errors` - Array of error objects for failed uploads (only present when failures occur)
361
+ def upload_directory(source, bucket:, **options)
362
+ Aws::Plugins::UserAgent.metric('S3_TRANSFER', 'S3_TRANSFER_UPLOAD_DIRECTORY') do
363
+ executor = @executor || DefaultExecutor.new(max_threads: options.delete(:thread_count))
364
+ uploader = DirectoryUploader.new(client: @client, executor: executor, logger: @logger)
365
+ result = uploader.upload(source, bucket, **options.merge(http_chunk_size: resolve_http_chunk_size(options)))
366
+ executor.shutdown unless @executor
367
+ result
368
+ end
369
+ end
370
+
156
371
  # Uploads a file from disk to S3.
157
372
  #
158
373
  # # a small file are uploaded with PutObject API
@@ -202,8 +417,9 @@ module Aws
202
417
  # Files larger han or equal to `:multipart_threshold` are uploaded using the S3 multipart upload APIs.
203
418
  # Default threshold is `100MB`.
204
419
  #
205
- # @option options [Integer] :thread_count (10) Customize threads used in the multipart upload.
206
- # Only used when no custom executor is provided (creates {DefaultExecutor} with the given thread count).
420
+ # @option options [Integer] :thread_count (10)
421
+ # The number of threads to use for multipart uploads.
422
+ # Only used when no custom executor is provided to the {TransferManager}.
207
423
  #
208
424
  # @option option [Integer] :http_chunk_size (16384) Size in bytes for each chunk when streaming request bodies
209
425
  # over HTTP. Controls the buffer size used when sending data to S3. Larger values may improve throughput by
@@ -226,17 +442,7 @@ module Aws
226
442
  # @see Client#upload_part
227
443
  def upload_file(source, bucket:, key:, **options)
228
444
  upload_opts = options.merge(bucket: bucket, key: key)
229
- http_chunk_size =
230
- if defined?(JRUBY_VERSION)
231
- nil
232
- else
233
- chunk = upload_opts.delete(:http_chunk_size)
234
- if chunk && chunk < Aws::Plugins::ChecksumAlgorithm::DEFAULT_TRAILER_CHUNK_SIZE
235
- raise ArgumentError, ':http_chunk_size must be at least 16384 bytes (16KB)'
236
- end
237
-
238
- chunk
239
- end
445
+ http_chunk_size = resolve_http_chunk_size(upload_opts)
240
446
 
241
447
  executor = @executor || DefaultExecutor.new(max_threads: upload_opts.delete(:thread_count))
242
448
  uploader = FileUploader.new(
@@ -316,6 +522,19 @@ module Aws
316
522
  executor.shutdown unless @executor
317
523
  true
318
524
  end
525
+
526
+ private
527
+
528
+ def resolve_http_chunk_size(opts)
529
+ return if defined?(JRUBY_VERSION)
530
+
531
+ chunk = opts.delete(:http_chunk_size)
532
+ if chunk && chunk < Aws::Plugins::ChecksumAlgorithm::DEFAULT_TRAILER_CHUNK_SIZE
533
+ raise ArgumentError, ':http_chunk_size must be at least 16384 bytes (16KB)'
534
+ end
535
+
536
+ chunk
537
+ end
319
538
  end
320
539
  end
321
540
  end