1 package software.amazon.awssdk.services.s3.transfer; 2 3 /** 4 * The S3 Transfer Manager is a library that allows users to easily and 5 * optimally upload and downloads to and from S3. 6 * <p> 7 * The list of features includes: 8 * <ul> 9 * <li>Parallel uploads and downloads</li> 10 * <li>Bandwidth limiting</li> 11 * <li>Pause and resume of transfers</li> 12 * </ul> 13 * <p> 14 * <b>Usage Example:</b> 15 * <pre> 16 * {@code 17 * // Create using all default configuration values 18 * S3TransferManager tm = S3TranferManager.create(); 19 * 20 * // Using custom configuration values to set max upload speed to avoid 21 * // saturating the network interface. 22 * S3TransferManager tm = S3TransferManager.builder() 23 * .maxUploadBytesSecond(32 * 1024 * 1024) // 32 MiB 24 * .build() 25 * .build(); 26 * } 27 * </pre> 28 */ 29 public interface S3TransferManager { 30 /** 31 * Download an object identified by the bucket and key from S3 to the given 32 * file. 33 * <p> 34 * <b>Usage Example:</b> 35 * <pre> 36 * {@code 37 * // Initiate transfer 38 * Download myFileDownload = tm.download(BUCKET, KEY, Paths.get("/tmp/myFile.txt"); 39 * // Wait for transfer to complete 40 * myFileDownload().completionFuture().join(); 41 * } 42 * </pre> 43 * 44 */ download(String bucket, String key, Path file)45 default Download download(String bucket, String key, Path file) { 46 return download(DownloadObjectRequest.builder() 47 .downloadSpecification(DownloadObjectSpecification.fromApiRequest(GetObjectRequest.builder() 48 .bucket(bucket) 49 .key(key) 50 .build())) 51 .build(), 52 file); 53 } 54 55 /** 56 * Download an object using an S3 presigned URL to the given file. 57 * <p> 58 * <b>Usage Example:</b> 59 * <pre> 60 * {@code 61 * // Initiate transfer 62 * Download myFileDownload = tm.download(myPresignedUrl, Paths.get("/tmp/myFile.txt"); 63 * // Wait for transfer to complete 64 * myFileDownload()completionFuture().join(); 65 * } 66 * </pre> 67 */ download(URL presignedUrl, Path file)68 default Download download(URL presignedUrl, Path file) { 69 return download(DownloadObjectRequest.builder() 70 .downloadSpecification(DownloadObjectSpecification.fromPresignedUrl(presignedUrl)) 71 .build(), 72 file); 73 } 74 /** 75 * Download an object in S3 to the given file. 76 * 77 * <p> 78 * <b>Usage Example:</b> 79 * <pre> 80 * {@code 81 * // Initiate the transfer 82 * Download myDownload = tm.download(DownloadObjectRequest.builder() 83 * .downloadObjectSpecification(DownloadObjectSpecification.fromApiRequest( 84 * GetObjectRequest.builder() 85 * .bucket(BUCKET) 86 * .key(KEY) 87 * .build())) 88 * // Set the known length of the object to avoid a HeadObject call 89 * .size(1024 * 1024 * 5) 90 * .build(), 91 * Paths.get("/tmp/myFile.txt")); 92 * // Wait for the transfer to complete 93 * myDownload.completionFuture().join(); 94 * } 95 * </pre> 96 */ download(DownloadObjectRequest request, Path file)97 Download download(DownloadObjectRequest request, Path file); 98 99 /** 100 * Resume a previously paused object download. 101 */ resumeDownloadObject(DownloadObjectState downloadObjectState)102 Download resumeDownloadObject(DownloadObjectState downloadObjectState); 103 104 /** 105 * Download the set of objects from the bucket with the given prefix to a directory. 106 * <p> 107 * The transfer manager will use '/' as the path delimiter. 108 * <p> 109 * <b>Usage Example:</b> 110 * <pre> 111 * {@code 112 * DownloadDirectory myDownload = tm.downloadDirectory(myBucket, myPrefix, Paths.get("/tmp"); 113 * myDowload.completionFuture().join(); 114 * } 115 * </pre> 116 * 117 * @param bucket The bucket. 118 * @param prefix The prefix. 119 * @param destinationDirectory The directory where the objects will be 120 * downloaded to. 121 */ downloadDirectory(String bucket, String prefix, Path destinationDirectory)122 DownloadDirectory downloadDirectory(String bucket, String prefix, Path destinationDirectory); 123 124 /** 125 * Upload a directory of files to the given S3 bucket and under the given 126 * prefix. 127 * <p> 128 * <b>Usage Example:</b> 129 * <pre> 130 * {@code 131 * UploadDirectory myUpload = tm.uploadDirectory(myBucket, myPrefix, Paths.get("/path/to/my/directory)); 132 * myUpload.completionFuture().join(); 133 * } 134 * </pre> 135 */ uploadDirectory(String bucket, String prefix, Path direcrtory)136 UploadDirectory uploadDirectory(String bucket, String prefix, Path direcrtory); 137 138 /** 139 * Upload a file to S3. 140 * <p> 141 * <b>Usage Example:</b> 142 * <pre> 143 * {@code 144 * UploadObject myUpload = tm.uploadObject(myBucket, myKey, Paths.get("myFile.txt")); 145 * myUpload.completionFuture().join(); 146 * } 147 * </pre> 148 */ upload(String bucket, String key, Path file)149 default Upload upload(String bucket, String key, Path file) { 150 return upload(UploadObjectRequest.builder() 151 .uploadSpecification(UploadObjectSpecification.fromApiRequest(PutObjectRequest.builder() 152 .bucket(bucket) 153 .key(key) 154 .build())) 155 .build(), 156 file); 157 } 158 159 /** 160 * Upload a file to S3 using the given presigned URL. 161 * <p> 162 * <b>Usage Example:</b> 163 * <pre> 164 * {@code 165 * Upload myUpload = tm.upload(myPresignedUrl, Paths.get("myFile.txt")); 166 * myUpload.completionFuture().join(); 167 * } 168 * </pre> 169 */ upload(URL presignedUrl, Path file)170 default Upload upload(URL presignedUrl, Path file) { 171 return upload(UploadObjectRequest.builder() 172 .uploadSpecification(UploadObjectSpecification.fromPresignedUrl(presignedUrl)) 173 .build(), 174 file); 175 } 176 177 /** 178 * Upload a file to S3. 179 */ upload(UploadObjectRequest request, Path file)180 Upload upload(UploadObjectRequest request, Path file); 181 182 /** 183 * Resume a previously paused object upload. 184 */ resumeUploadObject(UploadObjectState uploadObjectState)185 Upload resumeUploadObject(UploadObjectState uploadObjectState); 186 187 /** 188 * Create an {@code S3TransferManager} using the default values. 189 */ create()190 static S3TransferManager create() { 191 return builder().build(); 192 } 193 builder()194 static S3TransferManager.Builder builder() { 195 return ...; 196 } 197 198 interface Builder { 199 /** 200 * The custom S3AsyncClient this transfer manager will use to make calls 201 * to S3. 202 */ s3client(S3AsyncClient s3Client)203 Builder s3client(S3AsyncClient s3Client); 204 205 /** 206 * The max number of requests the Transfer Manager will have at any 207 * point in time. This must be less than or equal to the max concurrent 208 * setting on the S3 client. 209 */ maxConcurrency(Integer maxConcurrency)210 Builder maxConcurrency(Integer maxConcurrency); 211 212 /** 213 * The aggregate max upload rate in bytes per second over all active 214 * upload transfers. The default is unlimited. 215 */ maxUploadBytesPerSecond(Long maxUploadBytesPerSecond)216 Builder maxUploadBytesPerSecond(Long maxUploadBytesPerSecond); 217 218 /** 219 * The aggregate max download rate in bytes per second over all active 220 * download transfers. The default value is unlimited. 221 */ maxDownloadBytesPerSecond(Long maxDownloadBytesPerSecond)222 Builder maxDownloadBytesPerSecond(Long maxDownloadBytesPerSecond); 223 224 /** 225 * Add a progress listener to the currently configured list of 226 * listeners. 227 */ addProgressListener(TransferProgressListener progressListener)228 Builder addProgressListener(TransferProgressListener progressListener); 229 230 /** 231 * Set the list of progress listeners, overwriting any currently 232 * configured list. 233 */ progressListeners(Collection<? extends TransferProgressListener> progressListeners)234 Builder progressListeners(Collection<? extends TransferProgressListener> progressListeners); 235 build()236 S3TransferManager build(); 237 } 238 } 239 240 /** 241 * Configuration object for multipart downloads. 242 */ 243 public interface MultipartDownloadConfiguration { 244 /** 245 * Whether multipart downloads are enabled. 246 */ enableMultipartDownloads()247 public Boolean enableMultipartDownloads(); 248 249 /** 250 * The minimum size for an object to be downloaded in multiple parts. 251 */ multipartDownloadThreshold()252 public Long multipartDownloadThreshold(); 253 254 /** 255 * The maximum number of parts objects are to be downloaded in. 256 */ maxDownloadPartCount()257 public Integer maxDownloadPartCount(); 258 259 /** 260 * The minimum size for each part. 261 */ minDownloadPartSize()262 public Long minDownloadPartSize(); 263 } 264 265 /** 266 * Configuration object for multipart uploads. 267 */ 268 public final class MultipartUploadConfiguration { 269 /** 270 * Whether multipart uploads should be enabled. 271 */ enableMultipartUploads()272 public Boolean enableMultipartUploads(); 273 274 /** 275 * The minimum size for an object to be uploaded in multipe parts. 276 */ multipartUploadThreshold()277 public Long multipartUploadThreshold(); 278 279 /** 280 * The maximum number of perts to upload an object in. 281 */ maxUploadPartCount()282 public Integer maxUploadPartCount(); 283 284 /** 285 * The minimum size for each uploaded part. 286 */ minUploadPartSize()287 public Long minUploadPartSize(); 288 } 289 290 /** 291 * Override configuration for a single transfer. 292 */ 293 public interface TransferOverrideConfiguration { 294 /** 295 * The maximum rate for this transfer in bytes per second. 296 */ maxTransferBytesPerSecond()297 Long maxTransferBytesPerSecond(); 298 299 /** 300 * Override configuration for multipart downloads. 301 */ multipartDownloadConfiguration()302 MultipartDownloadConfiguration multipartDownloadConfiguration(); 303 304 /** 305 * Override configuration for multipart uploads. 306 */ multipartUploadConfiguration()307 MultipartUploadConfiguration multipartUploadConfiguration(); 308 } 309 310 311 /** 312 * A factory capable of creating the streams for individual parts of a given 313 * object to be uploaded to S3. 314 * <p> 315 * There is no ordering guaranatee for when {@link 316 * #streamForPart(PartUploadContext)} is called. 317 */ 318 public interface TransferRequestBody { 319 /** 320 * Return the stream for the object part described by given {@link 321 * PartUploadContext}. 322 * 323 * @param context The context describing the part to be uploaded. 324 * @return The part stream. 325 */ requestBodyForPart(PartUploadContext context)326 Publisher<ByteBuffer> requestBodyForPart(PartUploadContext context); 327 328 /** 329 * Return the stream for a entire object to be uploaded as a single part. 330 */ requestBodyForObject(SinglePartUploadContext context)331 Publisher<ByteBuffer> requestBodyForObject(SinglePartUploadContext context); 332 333 /** 334 * Create a factory that creates streams for individual parts of the given 335 * file. 336 * 337 * @param file The file whose parts the factory will create streams for. 338 * @return The stream factory. 339 */ forFile(Path file)340 static ObjectPartStreamCreator forFile(Path file) { 341 return ...; 342 } 343 } 344 345 /** 346 * A factory capable of creating the {@link AsyncResponseTransformer} to handle 347 * each downloaded object part. 348 * <p> 349 * There is no ordering guarantee for when {@link 350 * #transformerForPart(PartDownloadContext)} invocations. It is invoked when the 351 * response from S3 is received for the given part. 352 */ 353 public interface TransferResponseTransformer { 354 /** 355 * Return a transformer for downloading a single part of an object. 356 */ transformerForPart(MultipartDownloadContext context)357 AsyncResponseTransformer<GetObjectResponse, ?> transformerForPart(MultipartDownloadContext context); 358 359 /** 360 * Return a transformer for downloading an entire object as a single part. 361 */ 362 AsyncResponseTransformer<GetObjectResponse, ?> transformerForObject(SinglePartDownloadContext context) 363 364 /** 365 * Return a factory capable of creating transformers that will recombine the 366 * object parts to a single file on disk. 367 */ 368 static TransferResponseTransformer forFile(Path file) { 369 return ...; 370 } 371 } 372 373 /** 374 * The context object for the upload of an object part to S3. 375 */ 376 public interface MultipartUploadContext { 377 /** 378 * The original upload request given to the transfer manager. 379 */ uploadRequest()380 UploadObjectRequest uploadRequest(); 381 382 /** 383 * The request sent to S3 to initiate the multipart upload. 384 */ createMultipartRequest()385 CreateMultipartUploadRequest createMultipartRequest(); 386 387 /** 388 * The upload request to be sent to S3 for this part. 389 */ uploadPartRequest()390 UploadPartRequest uploadPartRequest(); 391 392 /** 393 * The offset from the beginning of the object where this part begins. 394 */ partOffset()395 long partOffset(); 396 } 397 398 public interface SinglePartUploadContext { 399 /** 400 * The original upload request given to the transfer manager. 401 */ uploadRequest()402 UploadObjectRequest uploadRequest(); 403 404 /** 405 * The request to be sent to S3 to upload the object as a single part. 406 */ objectRequest()407 PutObjectRequest objectRequest(); 408 } 409 410 /** 411 * Context object for an individual object part for a multipart download. 412 */ 413 public interface MultipartDownloadContext { 414 /** 415 * The original download request given to the Transfer Manager. 416 */ downloadRequest()417 DownloadObjectRequest downloadRequest(); 418 419 /** 420 * The part number. 421 */ partNumber()422 int partNumber(); 423 424 /** 425 * The offset from the beginning of the object where this part begins. 426 */ partOffset()427 long partOffset(); 428 429 /** 430 * The size of the part requested in bytes. 431 */ size()432 long size(); 433 434 /** 435 * Whether this is the last part of the object. 436 */ isLastPart()437 boolean isLastPart(); 438 } 439 440 /** 441 * Context object for a single part download of an object. 442 */ 443 public interface SinglePartDownloadContext { 444 /** 445 * The original download request given to the Transfer Manager. 446 */ downloadRequest()447 DownloadObjectRequest downloadRequest(); 448 449 /** 450 * The request sent to S3 for this object. This is empty if downloading a presigned URL. 451 */ objectRequest()452 GetObjectRequest objectRequest(); 453 } 454 455 /** 456 * Progress listener for a Transfer. 457 * <p> 458 * The SDK guarantees that calls to {@link #transferProgressEvent(EventContext)} 459 * are externally synchronized. 460 */ 461 public interface TransferProgressListener { 462 /** 463 * Called when a new progress event is available for a Transfer. 464 * 465 * @param ctx The context object for the given transfer event. 466 */ transferProgressEvent(EventContext ctx)467 void transferProgressEvent(EventContext ctx); 468 469 interface EventContext { 470 /** 471 * The transfer this listener associated with. 472 */ transfer()473 Transfer transfer(); 474 } 475 476 interface Initiated extends EventContext { 477 /** 478 * The amount of time that has elapsed since the transfer was 479 * initiated. 480 */ elapsedTime()481 Duration elapsedTime(); 482 } 483 484 interface BytesTransferred extends Initiated { 485 /** 486 * The transfer request for the object whose bytes were transferred. 487 */ objectRequest()488 TransferObjectRequest objectRequest(); 489 490 /** 491 * The number of bytes transferred for this event. 492 */ bytes()493 long bytes(); 494 495 /** 496 * The total size of the object. 497 */ size()498 long size(); 499 500 /** 501 * If the transfer of the given object is complete. 502 */ complete()503 boolean complete(); 504 } 505 506 interface Completed extends Initiated { 507 } 508 509 interface Cancelled extends Initiated { 510 } 511 512 interface Failed extends Initiated { 513 /** 514 * The error. 515 */ error()516 Throwable error(); 517 } 518 } 519 520 521 /** 522 * A download transfer of a single object from S3. 523 */ 524 public interface Download extends Transfer { 525 @Override pause()526 DownloadObjectState pause(); 527 } 528 529 /** 530 * An upload transfer of a single object to S3. 531 */ 532 public interface Upload extends Transfer { 533 @Override pause()534 UploadObjectState pause(); 535 } 536 537 /** 538 * The state of an object download. 539 */ 540 public interface DownloadState extends TransferState { 541 /** 542 * Persist this state so it can later be resumed. 543 */ persistTo(OutputStream os)544 void persistTo(OutputStream os); 545 546 /** 547 * Load a persisted transfer which can then be resumed. 548 */ loadFrom(Inputstream is)549 static DownloadState loadFrom(Inputstream is) { 550 ... 551 } 552 } 553 554 /** 555 * The state of an object upload. 556 */ 557 public interface UploadState extends TransferState { 558 /** 559 * Persist this state so it can later be resumed. 560 */ persistTo(OutputStream os)561 void persistTo(OutputStream os); 562 563 /** 564 * Load a persisted transfer which can then be resumed. 565 */ loadFrom(Inputstream is)566 static UploadState loadFrom(Inputstream is) { 567 ... 568 } 569 } 570 571 /** 572 * Represents the transfer of one or more objects to or from S3. 573 */ 574 public interface Transfer { 575 completionFuture()576 CompletableFuture<? extends CompletedTransfer> completionFuture(); 577 578 /** 579 * Pause this transfer, cancelling any requests in progress. 580 * <p> 581 * The returned state object can be used to resume this transfer at a later 582 * time. 583 * 584 * @throws IllegalStateException If this transfer is completed or cancelled. 585 * @throws UnsupportedOperationException If the transfer does not support 586 * pause and resume. 587 */ pause()588 TransferState pause(); 589 } 590 591 public interface CompletedTransfer { 592 /** 593 * The metrics for this transfer. 594 */ metrics()595 TransferMetrics metrics(); 596 } 597 598 /** 599 * Metrics for a completed transfer. 600 */ 601 public interface TransferMetrics { 602 /** 603 * The number of milliseconds that elapsed before this transfer completed. 604 */ elapsedMillis()605 long elapsedMillis(); 606 607 /** 608 * The total number of bytes transferred. 609 */ bytesTransferred()610 long bytesTransferred(); 611 } 612 613 614 /** 615 * A request to download an object. The object to download is specified using 616 * the {@link DownloadObjectSpecification} union type. 617 */ 618 public class DownloadObjectRequest extends AbstractTransferRequest { 619 /** 620 * The specification for how to download the object. 621 */ downloadSpecification()622 DownloadObjectSpecification downloadSpecification(); 623 624 /** 625 * The size of the object to be downloaded. 626 */ size()627 public Long size(); 628 forPresignedUrl(URL presignedUrl)629 public static DownloadObjectRequest forPresignedUrl(URL presignedUrl) { 630 ... 631 } 632 forBucketAndKey(String bucket, String key)633 public static DownloadObjectRequest forBucketAndKey(String bucket, String key) { 634 ... 635 } 636 637 public interface Builder extends AbstractTransferRequest.Builder { 638 /** 639 * The specification for how to download the object. 640 */ downloadSpecification(DownloadObjectSpecification downloadSpecification)641 Builder downloadSpecification(DownloadObjectSpecification downloadSpecification); 642 643 /** 644 * Set the override configuration for this request. 645 */ 646 @Override overrideConfiguration(TransferOverrideConfiguration config)647 Builder overrideConfiguration(TransferOverrideConfiguration config); 648 649 /** 650 * Set the progress listeners for this request. 651 */ 652 @Override progressListeners(Collection<TransferProgressListener> progressListeners)653 Builder progressListeners(Collection<TransferProgressListener> progressListeners); 654 655 /** 656 * Add an additional progress listener for this request, appending it to 657 * the list of currently configured listeners on this request. 658 */ 659 @Override addProgressListener(TransferProgressListener progressListener)660 Builder addProgressListener(TransferProgressListener progressListener); 661 662 /** 663 * Set the optional size of the object to be downloaded. 664 */ size(Long size)665 Builder size(Long size); 666 build()667 DownloadObjectRequest build(); 668 } 669 } 670 671 /** 672 * Union type to contain the different ways to express an object download from 673 * S3. 674 */ 675 public class DownloadObjectSpecification { 676 /** 677 * Return this specification as a presigned URL. 678 * 679 * @throws IllegalStateException If this specifier is not a presigned URL. 680 */ asPresignedUrl()681 URL asPresignedUrl(); 682 683 /** 684 * Return this specification as a {@link GetObjectRequest API request}. 685 * 686 * @throws IllegalStateException If this specifier is not an API request. 687 */ asApiRequest()688 GetObjectRequest asApiRequest(); 689 690 /** 691 * Returns {@code true} if this is a presigned URL, {@code false} otherwise. 692 */ isPresignedUrl()693 boolean isPresignedUrl(); 694 695 /** 696 * Returns {@code true} if this is an API request, {@code false} otherwise. 697 */ isApiRequest()698 boolean isApiRequest(); 699 700 /** 701 * Create an instance from a presigned URL. 702 */ fromPresignedUrl(URL presignedUrl)703 static DownloadObjectSpecification fromPresignedUrl(URL presignedUrl) { 704 ... 705 } 706 707 /** 708 * Create an instance from an API request. 709 */ fromApiRequest(GetObjectRequest apiRequest)710 static DownloadObjectSpecification fromApiRequest(GetObjectRequest apiRequest) { 711 ... 712 } 713 } 714 715 /** 716 * A request to upload an object. The object to upload is specified using the 717 * {@link UploadObjectSpecification} union type. 718 */ 719 public class UploadObjectRequest extends AbstractTransferRequest { 720 /** 721 * The specification for how to upload the object. 722 */ uploadSpecification()723 UploadbjectSpecification uploadSpecification(); 724 725 /** 726 * The size of the object to be uploaded. 727 */ size()728 long size(); 729 forPresignedUrl(URL presignedUrl)730 public static UploadObjectRequest forPresignedUrl(URL presignedUrl) { 731 ... 732 } 733 forBucketAndKey(String bucket, String key)734 public static UploadObjectRequest forBucketAndKey(String bucket, String key) { 735 ... 736 } 737 738 public interface Builder extends AbstractTransferRequest.Builder { 739 /** 740 * The specification for how to upload the object. 741 */ uploadSpecification(UploadObjectSpecification uploadSpecification)742 Builder uploadSpecification(UploadObjectSpecification uploadSpecification); 743 744 /** 745 * Set the override configuration for this request. 746 */ 747 @Override overrideConfiguration(TransferOverrideConfiguration config)748 Builder overrideConfiguration(TransferOverrideConfiguration config); 749 750 /** 751 * Set the progress listeners for this request. 752 */ 753 @Override progressListeners(Collection<TransferProgressListener> progressListeners)754 Builder progressListeners(Collection<TransferProgressListener> progressListeners); 755 756 /** 757 * Add an additional progress listener for this request, appending it to 758 * the list of currently configured listeners on this request. 759 */ 760 @Override addProgressListener(TransferProgressListener progressListener)761 Builder addProgressListener(TransferProgressListener progressListener); 762 build()763 UploadObjectRequest build(); 764 } 765 } 766 767 /** 768 * Union type to contain the different ways to express an object upload from 769 * S3. 770 */ 771 public class UploadObjectSpecification { 772 /** 773 * Return this specification as a presigned URL. 774 * 775 * @throws IllegalStateException If this specifier is not a presigned URL. 776 */ asPresignedUrl()777 URL asPresignedUrl(); 778 779 /** 780 * Return this specification as a {@link PutObjectRequest API request}. 781 * 782 * @throws IllegalStateException If this specifier is not an API request. 783 */ asApiRequest()784 PutObjectRequest asApiRequest(); 785 786 /** 787 * Returns {@code true} if this is a presigned URL, {@code false} otherwise. 788 */ isPresignedUrl()789 boolean isPresignedUrl(); 790 791 /** 792 * Returns {@code true} if this is an API request, {@code false} otherwise. 793 */ isApiRequest()794 boolean isApiRequest(); 795 796 /** 797 * Create an instance from a presigned URL. 798 */ fromPresignedUrl(URL presignedUrl)799 static UploadObjectSpecification fromPresignedUrl(URL presignedUrl) { 800 ... 801 } 802 803 /** 804 * Create an instance from an API request. 805 */ fromApiRequest(PutObjectRequest apiRequest)806 static UploadObjectSpecification fromApiRequest(PutObjectRequest apiRequest) { 807 ... 808 } 809 } 810