Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Migrasikan Manajer Transfer dari versi 1 ke versi 2 AWS SDK untuk Java
Panduan migrasi ini mencakup perbedaan utama antara Transfer Manager v1 dan S3 Transfer Manager v2, termasuk perubahan konstruktor, pemetaan metode, dan contoh kode untuk operasi umum. Setelah meninjau perbedaan ini, Anda dapat berhasil memigrasikan kode Transfer Manager yang ada untuk memanfaatkan peningkatan kinerja dan operasi asinkron di v2.
Tentang alat migrasi AWS SDK
AWS SDK untuk Java Ini menyediakan alat migrasi otomatis yang dapat memigrasikan sebagian besar API Manajer Transfer v1 ke v2. Namun, alat migrasi tidak mendukung beberapa fitur Manajer Transfer v1. Untuk kasus ini, Anda perlu memigrasikan kode Transfer Manager secara manual menggunakan panduan dalam topik ini.
Sepanjang panduan ini, indikator Status Migrasi menunjukkan apakah alat migrasi dapat secara otomatis memigrasikan konstruktor, metode, atau fitur:
-
✅ Didukung: Alat migrasi dapat secara otomatis mengubah kode ini
-
❌ Tidak Didukung: Anda perlu memigrasi kode secara manual
Bahkan untuk item yang ditandai sebagai “Didukung,” tinjau hasil migrasi dan uji secara menyeluruh. Migrasi Transfer Manager melibatkan perubahan arsitektur yang signifikan dari operasi sinkron ke asinkron.
Gambaran Umum
S3 Transfer Manager v2 memperkenalkan perubahan signifikan pada Transfer Manager API. S3 Transfer Manager v2 dibangun di atas operasi asinkron dan memberikan kinerja yang lebih baik, terutama ketika Anda menggunakan klien Amazon S3 berbasis CRT AWS .
Perbedaan utama
-
Package:
com.amazonaws.services.s3.transfer
→software.amazon.awssdk.transfer.s3
-
Nama kelas:
TransferManager
→S3TransferManager
-
Ketergantungan klien: Klien Amazon S3 sinkron → Klien Amazon S3 asinkron ()
S3AsyncClient
-
Arsitektur: Operasi sinkron → Operasi asinkron dengan
CompletableFuture
-
Kinerja: Ditingkatkan dengan dukungan AWS klien berbasis CRT
Perubahan tingkat tinggi
Aspek | V1 | V2 |
---|---|---|
Ketergantungan Maven | aws-java-sdk-s3 |
s3-transfer-manager |
Package | com.amazonaws.services.s3.transfer |
software.amazon.awssdk.transfer.s3 |
Kelas utama | TransferManager |
S3TransferManager |
Klien Amazon S3 | AmazonS3 (sinkronisasi) |
S3AsyncClient (asinkron) |
Jenis pengembalian | Operasi pemblokiran | CompletableFuture<T> |
Ketergantungan Maven
V1 | V2 |
---|---|
|
|
1 Versi terbaru
Migrasi konstruktor klien
Konstruktor yang didukung (migrasi otomatis)
V1 konstruktor | V2 setara | Status migrasi |
---|---|---|
new TransferManager() |
S3TransferManager.create() |
✅ Didukung |
TransferManagerBuilder.
defaultTransferManager() |
S3TransferManager.create() |
✅ Didukung |
TransferManagerBuilder.
standard().build() |
S3TransferManager.builder().build() |
✅ Didukung |
new TransferManager(AWSCredentials) |
S3TransferManager.builder()
.s3Client(S3AsyncClient.builder()
.credentialsProvider(...).build())
.build() |
✅ Didukung |
new TransferManager(
AWSCredentialsProvider) |
S3TransferManager.builder()
.s3Client(S3AsyncClient.builder()
.credentialsProvider(...).build())
.build() |
✅ Didukung |
Konstruktor yang tidak didukung (diperlukan migrasi manual)
V1 konstruktor | V2 setara | Catatan migrasi |
---|---|---|
new TransferManager(AmazonS3) |
Migrasi manual diperlukan | Buat secara S3AsyncClient terpisah |
new TransferManager(AmazonS3,
ExecutorService) |
Migrasi manual diperlukan | Buat S3AsyncClient dan konfigurasikan eksekutor |
new TransferManager(AmazonS3,
ExecutorService, boolean) |
Migrasi manual diperlukan | shutDownThreadPools parameter tidak didukung |
Contoh migrasi manual
Kode V1:
AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
TransferManager transferManager = new TransferManager(s3Client);
Kode V2:
// Create an `S3AsyncClient` with similar configuration
S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
// Provide the configured `S3AsyncClient` to the S3 transfer manager builder.
S3TransferManager transferManager = S3TransferManager.builder()
.s3Client(s3AsyncClient)
.build();
Migrasi metode klien
Saat ini, alat migrasi mendukung dasar copy
download
,upload
,uploadDirectory
,downloadDirectory
,resumeDownload
, dan resumeUpload
metode.
Metode transfer inti
Metode V1 | Metode V2 | Kembalikan perubahan tipe | Status migrasi |
---|---|---|---|
upload(String, String, File) |
uploadFile(UploadFileRequest) |
Upload → FileUpload |
✅ Didukung |
upload(PutObjectRequest) |
upload(UploadRequest) |
Upload → Upload |
✅ Didukung |
download(String, String, File) |
downloadFile(DownloadFileRequest) |
Download → FileDownload |
✅ Didukung |
download(GetObjectRequest, File) |
downloadFile(DownloadFileRequest) |
Download → FileDownload |
✅ Didukung |
copy(String, String, String, String) |
copy(CopyRequest) |
Copy → Copy |
✅ Didukung |
copy(CopyObjectRequest) |
copy(CopyRequest) |
Copy → Copy |
✅ Didukung |
uploadDirectory(String, String,
File, boolean) |
uploadDirectory(
UploadDirectoryRequest) |
MultipleFileUpload →
DirectoryUpload |
✅ Didukung |
downloadDirectory(String, String, File) |
downloadDirectory(
DownloadDirectoryRequest) |
MultipleFileDownload →
DirectoryDownload |
✅ Didukung |
Metode transfer yang dapat dilanjutkan
Metode V1 | Metode V2 | Status migrasi |
---|---|---|
resumeUpload(PersistableUpload) |
resumeUploadFile(ResumableFileUpload) |
✅ Didukung |
resumeDownload(PersistableDownload) |
resumeDownloadFile(ResumableFileDownload) |
✅ Didukung |
Metode siklus hidup
Metode V1 | Metode V2 | Status migrasi |
---|---|---|
shutdownNow() |
close() |
✅ Didukung |
shutdownNow(boolean) |
Sesuaikan kode secara manual menggunakan close() metode |
❌ Tidak Didukung |
Metode klien V1 yang tidak didukung
Metode V1 | V2 alternatif | Catatan |
---|---|---|
abortMultipartUploads(String, Date) |
Gunakan klien Amazon S3 tingkat rendah | ❌ Tidak Didukung |
getAmazonS3Client() |
Simpan referensi secara terpisah | ❌ Tidak Didukung; tidak ada pengambil di v2 |
getConfiguration() |
Simpan referensi secara terpisah | ❌ Tidak Didukung; tidak ada pengambil di v2 |
uploadFileList(...) |
Lakukan beberapa uploadFile() panggilan |
❌ Tidak Didukung |
copy metode dengan TransferStateChangeListener parameter |
Gunakan TransferListener |
Lihat contoh migrasi manual |
download metode dengan S3ProgressListener parameter |
Gunakan TransferListener |
Lihat contoh migrasi manual |
|
Lihat contoh migrasi manual | |
upload metode dengan ObjectMetadataProvider parameter |
Tetapkan metadata dalam permintaan | Lihat contoh migrasi manual |
uploadDirectory metode dengan *Provider parameter |
Tetapkan tag dalam permintaan | Lihat contoh migrasi manual |
copy
metode dengan TransferStateChangeListener
parameter
-
copy(CopyObjectRequest copyObjectRequest, AmazonS3 srcS3, TransferStateChangeListener stateChangeListener)
-
copy(CopyObjectRequest copyObjectRequest, TransferStateChangeListener stateChangeListener)
// V1 ---------------------------------------------------------------------------------------------- // Initialize source S3 client AmazonS3 s3client = AmazonS3ClientBuilder.standard() .withRegion("us-west-2") .build(); // Initialize Transfer Manager TransferManager tm = TransferManagerBuilder.standard() .withS3Client(srcS3) .build(); CopyObjectRequest copyObjectRequest = new CopyObjectRequest( "amzn-s3-demo-source-bucket", "source-key", "amzn-s3-demo-destination-bucket", "destination-key" ); TransferStateChangeListener stateChangeListener = new TransferStateChangeListener() { @Override public void transferStateChanged(Transfer transfer, TransferState state) { //Implementation of the TransferStateChangeListener } }; Copy copy = tm.copy(copyObjectRequest, srcS3, stateChangeListener); // V2 ---------------------------------------------------------------------------------------------- S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .region(Region.US_WEST_2) .build(); S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build(); // Create transfer listener (equivalent to TransferStateChangeListener in v1) TransferListener transferListener = new TransferListener() { @Override public void transferInitiated(Context.TransferInitiated context) { //Implementation System.out.println("Transfer initiated"); } @Override public void bytesTransferred(Context.BytesTransferred context) { //Implementation System.out.println("Bytes transferred"); } @Override public void transferComplete(Context.TransferComplete context) { //Implementation System.out.println("Transfer completed!"); } @Override public void transferFailed(Context.TransferFailed context) { //Implementation System.out.println("Transfer failed"); } }; CopyRequest copyRequest = CopyRequest.builder() .copyObjectRequest(req -> req .sourceBucket("amzn-s3-demo-source-bucket") .sourceKey("source-key") .destinationBucket("amzn-s3-demo-destination-bucket") .destinationKey("destination-key") ) .addTransferListener(transferListener) // Configure the transferListener into the request .build(); Copy copy = transferManager.copy(copyRequest);
download
metode dengan S3ProgressListener
parameter
-
download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener)
-
download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis)
-
download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis, boolean resumeOnRetry)
// V1 ---------------------------------------------------------------------------------------------- S3ProgressListener progressListener = new S3ProgressListener() { @Override public void progressChanged(com.amazonaws.event.ProgressEvent progressEvent) { long bytes = progressEvent.getBytesTransferred(); ProgressEventType eventType = progressEvent.getEventType(); // Use bytes and eventType as needed } @Override public void onPersistableTransfer(PersistableTransfer persistableTransfer) { } }; Download download1 = tm.download(getObjectRequest, file, progressListener); Download download2 = tm.download(getObjectRequest, file, progressListener, timeoutMillis) Download download3 = tm.download(getObjectRequest, file, progressListener, timeoutMillis, true) // V2 ---------------------------------------------------------------------------------------------- TransferListener transferListener = new TransferListener() { @Override public void transferInitiated(Context.InitializedContext context) { // Equivalent to ProgressEventType.TRANSFER_STARTED_EVENT System.out.println("Transfer initiated"); } @Override public void bytesTransferred(Context.BytesTransferred context) { // Equivalent to ProgressEventType.REQUEST_BYTE_TRANSFER_EVENT long bytes = context.bytesTransferred(); System.out.println("Bytes transferred: " + bytes); } @Override public void transferComplete(Context.TransferComplete context) { // Equivalent to ProgressEventType.TRANSFER_COMPLETED_EVENT System.out.println("Transfer completed"); } @Override public void transferFailed(Context.TransferFailed context) { // Equivalent to ProgressEventType.TRANSFER_FAILED_EVENT System.out.println("Transfer failed: " + context.exception().getMessage()); } }; DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder() .getObjectRequest(getObjectRequest) .destination(file.toPath()) .addTransferListener(transferListener) .build(); // For download1 FileDownload download = transferManager.downloadFile(downloadFileRequest); // For download2 CompletedFileDownload completedFileDownload = download.completionFuture() .get(timeoutMillis, TimeUnit.MILLISECONDS); // For download3, the v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1. // If a download is interrupted, you need to start a new download request.
downloadDirectory
metode dengan 4 atau lebih parameter
-
downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry)
-
downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry, KeyFilter filter)
-
downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, KeyFilter filter)
// V1 ---------------------------------------------------------------------------------------------- KeyFilter filter = new KeyFilter() { @Override public boolean shouldInclude(S3ObjectSummary objectSummary) { //Filter implementation } }; MultipleFileDownload multipleFileDownload = tm.downloadDirectory(bucketName, keyPrefix, destinationDirectory, filter); // V2 ---------------------------------------------------------------------------------------------- // The v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1. // If a download is interrupted, you need to start a new download request. DownloadFilter filter = new DownloadFilter() { @Override public boolean test(S3Object s3Object) { // Filter implementation. } }; DownloadDirectoryRequest downloadDirectoryRequest = DownloadDirectoryRequest.builder() .bucket(bucketName) .filter(filter) .listObjectsV2RequestTransformer(builder -> builder.prefix(keyPrefix)) .destination(destinationDirectory.toPath()) .build(); DirectoryDownload directoryDownload = transferManager.downloadDirectory(downloadDirectoryRequest);
upload
metode dengan ObjectMetadata
parameter
-
upload(String bucketName, String key, InputStream input, ObjectMetadata objectMetadata)
// V1 ----------------------------------------------------------------------------------------------ObjectMetadata metadata = new ObjectMetadata(); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("text/plain"); // System-defined metadata metadata.setContentLength(22L); // System-defined metadata metadata.addUserMetadata("myKey", "myValue"); // User-defined metadata PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, metadata); Upload upload = transferManager.upload("amzn-s3-demo-bucket", "my-key", inputStream, metadata); // V2 ---------------------------------------------------------------------------------------------- /* When you use an InputStream to upload in V2, you should specify the content length and use `RequestBody.fromInputStream()`. If you don't provide the content length, the entire stream will be buffered in memory. If you can't determine the content length, we recommend using the CRT-based S3 client. */ Map<String, String> userMetadata = new HashMap<>(); userMetadata.put("x-amz-meta-myKey", "myValue"); PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket("amzn-s3-demo-bucket1") .key("k") .contentType("text/plain") //System-defined metadata usually has separate methods in the builder. .contentLength(22L) .metadata(userMetadata) //metadata() is only for user-defined metadata. .build(); UploadRequest uploadRequest = UploadRequest.builder() .putObjectRequest(putObjectRequest) .requestBody(AsyncRequestBody.fromInputStream(stream, 22L, executor)) .build(); transferManager.upload(uploadRequest).completionFuture().join();
uploadDirectory
dengan ObjectMetadataProvider
parameter
-
uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider)
-
uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider)
-
uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider, ObjectCannedAclProvider cannedAclProvider)
// V1 ---------------------------------------------------------------------------------------------- tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider) tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider) tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider, cannedAclProvider) // V2 ---------------------------------------------------------------------------------------------- UploadDirectoryRequest request = UploadDirectoryRequest.builder() .bucket(bucketName) .s3Prefix(virtualDirectoryKeyPrefix) .source(directory.toPath()) .maxDepth(includeSubdirectories ? Integer.MAX_VALUE : 1) .uploadFileRequestTransformer(builder -> { // 1.Replace `ObjectMetadataProvider`, `ObjectTaggingProvider`, and `ObjectCannedAclProvider` with an // `UploadFileRequestTransformer` that can combine the functionality of all three *Provider implementations. // 2. Convert your v1 `ObjectMetadata` to v2 `PutObjectRequest` parameters. // 3. Convert your v1 `ObjectTagging` to v2 `Tagging`. // 4. Convert your v1 `CannedAccessControlList` to v2 `ObjectCannedACL`. }) .build(); DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);
Migrasi objek model
Pada tahun AWS SDK for Java 2.x, banyak objek TransferManager
model telah didesain ulang, dan beberapa metode pengambil dan penyetel yang tersedia di objek model v1 tidak lagi didukung.
Di v2, Anda dapat menggunakan CompletableFuture<T>
kelas untuk melakukan tindakan saat transfer selesai — baik berhasil atau dengan pengecualian. Anda dapat menggunakan join()
metode ini untuk menunggu penyelesaian jika diperlukan.
Objek transfer inti
Kelas V1 | Kelas V2 | Status migrasi |
---|---|---|
TransferManager |
S3TransferManager |
✅ Didukung |
TransferManagerBuilder |
S3TransferManager.Builder |
✅ Didukung |
Transfer |
Transfer |
✅ Didukung |
AbortableTransfer |
Transfer |
✅ Didukung (tidak ada kelas terpisah) |
Copy |
Copy |
✅ Didukung |
Download |
FileDownload |
✅ Didukung |
Upload |
Upload / FileUpload |
✅ Didukung |
MultipleFileDownload |
DirectoryDownload |
✅ Didukung |
MultipleFileUpload |
DirectoryUpload |
✅ Didukung |
Objek ketekunan
Kelas V1 | Kelas V2 | Status migrasi |
---|---|---|
PersistableDownload |
ResumableFileDownload |
✅ Didukung |
PersistableUpload |
ResumableFileUpload |
✅ Didukung |
PersistableTransfer |
ResumableTransfer |
✅ Didukung |
PauseResult<T> |
Objek langsung yang dapat dilanjutkan | ❌ Tidak Didukung |
Objek hasil
Kelas V1 | Kelas V2 | Status migrasi |
---|---|---|
CopyResult |
CompletedCopy |
✅ Didukung |
UploadResult |
CompletedUpload |
✅ Didukung |
Objek konfigurasi
Kelas V1 | Kelas V2 | Status migrasi |
---|---|---|
TransferManagerConfiguration |
MultipartConfiguration (di klien Amazon S3) |
✅ Didukung |
TransferProgress |
TransferProgress + TransferProgressSnapshot |
✅ Didukung |
KeyFilter |
DownloadFilter |
✅ Didukung |
Objek yang tidak didukung
Kelas V1 | V2 alternatif | Status migrasi |
---|---|---|
PauseStatus |
Tidak didukung | ❌ Tidak Didukung |
UploadContext |
Tidak didukung | ❌ Tidak Didukung |
ObjectCannedAclProvider |
PutObjectRequest.builder().acl() |
❌ Tidak Didukung |
ObjectMetadataProvider |
PutObjectRequest.builder().metadata() |
❌ Tidak Didukung |
ObjectTaggingProvider |
PutObjectRequest.builder().tagging() |
❌ Tidak Didukung |
PresignedUrlDownload |
Tidak didukung | ❌ Tidak Didukung |
TransferManagerBuilder migrasi konfigurasi
Perubahan konfigurasi
Perubahan konfigurasi yang perlu Anda atur untuk manajer transfer v2 bergantung pada klien S3 mana yang Anda gunakan. Anda memiliki pilihan klien S3 AWS berbasis CRT atau klien async S3 berbasis Java standar. Untuk informasi tentang perbedaannya, lihat Klien S3 di AWS SDK for Java 2.x topiknya.
Perubahan perilaku
Operasi asinkron
V1 (pemblokiran):
Upload upload = transferManager.upload("amzn-s3-demo-bucket", "key", file);
upload.waitForCompletion(); // Blocks until complete
V2 (asinkron):
FileUpload upload = transferManager.uploadFile(UploadFileRequest.builder()
.putObjectRequest(PutObjectRequest.builder()
.bucket("amzn-s3-demo-bucket")
.key("key")
.build())
.source(file)
.build());
CompletedFileUpload result = upload.completionFuture().join(); // Blocks until complete
// Or handle asynchronously:
upload.completionFuture().thenAccept(result -> {
System.out.println("Upload completed: " + result.response().eTag());
});
Penanganan kesalahan
V1: Transfer direktori gagal sepenuhnya jika ada sub-permintaan yang gagal.
V2: Transfer direktori berhasil diselesaikan bahkan jika beberapa sub-permintaan gagal. Periksa kesalahan secara eksplisit:
DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);
CompletedDirectoryUpload result = directoryUpload.completionFuture().join();
// Check for failed transfers
if (!result.failedTransfers().isEmpty()) {
System.out.println("Some uploads failed:");
result.failedTransfers().forEach(failed ->
System.out.println("Failed: " + failed.exception().getMessage()));
}
Unduhan paralel melalui pengambilan rentang byte
Ketika fitur transfer paralel otomatis diaktifkan di SDK v2, Manajer Transfer S3 menggunakan pengambilan rentang byte untuk mengambil bagian tertentu dari objek secara paralel (unduhan multibagian). Cara objek diunduh dengan v2 tidak tergantung pada bagaimana objek awalnya diunggah. Semua unduhan dapat memperoleh manfaat dari throughput dan konkurensi yang tinggi.
Sebaliknya, dengan Transfer Manager v1, penting bagaimana objek awalnya diunggah. Manajer Transfer v1 mengambil bagian-bagian objek dengan cara yang sama seperti bagian-bagian yang diunggah. Jika objek awalnya diunggah sebagai objek tunggal, Manajer Transfer v1 tidak dapat mempercepat proses pengunduhan dengan menggunakan sub-permintaan.