Java thao tác với DigitalOcean Spaces sử dụng S3TransferManager
1. Thư viện
<!-- https://mvnrepository.com/artifact/software.amazon.awssdk/s3 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.21.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/software.amazon.awssdk/s3-transfer-manager -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-transfer-manager</artifactId>
<version>2.21.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/software.amazon.awssdk.crt/aws-crt -->
<dependency>
<groupId>software.amazon.awssdk.crt</groupId>
<artifactId>aws-crt</artifactId>
<version>0.28.0</version>
</dependency>
<!-- Log Library -->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<!-- Log Library -->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
</dependency>
2. Tạo đối tượng S3TransferManager
Tạo đối tượng S3TransferManager để tương tác với DigitalOcean Spaces Bucket hơi khác biệt một chút so với việc tạo đối tượng S3TransferManager để tương tác với Amazon S3 Bucket.
Bạn cần phải kiểm tra xem Spaces Bucket của bạn đang được đặt tại trung tâm dữ liệu nào, từ đó biết được "SLUG" của nó.
DigitalOcean Data centers
SlugMột chuỗi mà con người có thể đọc được, được sử dụng làm mã định danh duy nhất cho từng khu vực (Region).
Dưới đây là các phương thức tiện ích tạo đối tượng S3TransferManager cho phép bạn tương tác với Spaces Bucket.
MyS3TransferManagerUtils.java
package org.o7planning.java_14253_do_spaces.utils;
import java.net.URI;
import org.o7planning.java_14253_do_spaces.MyAccessKey;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.SizeConstant;
public class MyUtils {
//
// @digitalOceanSlug: nyc1, nyc2, fra1,..
// @see: https://docs.digitalocean.com/products/platform/availability-matrix/
//
public static S3TransferManager createS3TransferManager(String digitalOceanSlug) {
final Region region = Region.of(digitalOceanSlug);
final String endpointUrl = "https://" + digitalOceanSlug + ".digitaloceanspaces.com";
//
AwsCredentials credentials = AwsBasicCredentials.create( //
MyAccessKey.DO_ACCESS_KEY_ID, //
MyAccessKey.DO_SECRET_ACCESS_KEY //
);
StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(credentials);
S3AsyncClient s3AsyncClient = S3AsyncClient.builder() //
.credentialsProvider(credentialsProvider) //
.region(region) //
.endpointOverride(URI.create(endpointUrl)) // IMPORTANT for DigitalOcean
.build();
return S3TransferManager.builder().s3Client(s3AsyncClient).build();
}
//
// @digitalOceanSlug: nyc1, nyc2, fra1,..
// @see: https://docs.digitalocean.com/products/platform/availability-matrix/
//
// This method is currently not working (Need to wait for CRT to be supported by DigitalOcean)
// NOTE: 2023 November, CRT still is not supported by DigitalOcean. (*****)
// CRT: AWS Common Runtime (CRT)
// https://aws.amazon.com/blogs/developer/introducing-crt-based-s3-client-and-the-s3-transfer-manager-in-the-aws-sdk-for-java-2-x/
public static S3TransferManager createCrtS3TransferManager(String digitalOceanSlug) {
final Region region = Region.of(digitalOceanSlug);
final String endpointUrl = "https://" + digitalOceanSlug + ".digitaloceanspaces.com";
//
AwsCredentials credentials = AwsBasicCredentials.create( //
MyAccessKey.DO_ACCESS_KEY_ID, //
MyAccessKey.DO_SECRET_ACCESS_KEY //
);
StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(credentials);
S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder() // (*****)
.credentialsProvider(credentialsProvider) //
.region(region) //
.endpointOverride(URI.create(endpointUrl)) // IMPORTANT for DigitalOcean
.targetThroughputInGbps(20.0) //
.minimumPartSizeInBytes(10 * SizeConstant.MB) //
.build();
return S3TransferManager.builder().s3Client(s3AsyncClient).build();
}
}
Chú ý: Phương thức MyUtils.createCrtS3TransferManager chưa hoạt động với DO-Spaces tại thời điểm tôi viết bài viết này (Tháng 11-2023). Nó là một cách mới để tạo đối tượng S3TransferManager dựa trên thư viện Amazon CRT (AWS Common Runtime), nó giúp việc upload, download nhanh hơn 70%. Có lẽ cần thời gian để nó được DigitalOcean hỗ trợ.
Xem thêm các cách khác để tạo đối tượng AwsCredentialsProvider với "accessKeyId/secretAccessKey" được thiết lập tại các vị trí an toàn hơn thay vì code cứng trên mã Java. Chú ý: Bạn cũng cần một vài thay đổi nhỏ để đảm bảo nó làm việc với Spaces Bucket.
3. Upload file với S3TransferManager
Ví dụ đơn giản, upload một file lên Spaces Bucket sử dụng S3TransferManager.
S3TransferManagerUploadExample1.java
package org.o7planning.java_14253_do_spaces.example;
import java.nio.file.Paths;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionException;
import org.o7planning.java_14253_do_spaces.utils.MyUtils;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload;
import software.amazon.awssdk.transfer.s3.model.FileUpload;
import software.amazon.awssdk.transfer.s3.model.UploadFileRequest;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
public class S3TransferManagerUploadExample1 {
// DigitalOcean SLUG List:
// https://docs.digitalocean.com/products/platform/availability-matrix/
private static final String MY_DO_SLUG = "fra1";
private static final String MY_DO_SPACES_NAME = "my-do-spaces";
public static void uploadFile(S3TransferManager transferManager, String bucketName, //
String key, String filePath) {
// Create UploadFileRequest.
UploadFileRequest uploadFileRequest = UploadFileRequest.builder()
.putObjectRequest(b -> b.bucket(bucketName).key(key)) // bucketName & key
.addTransferListener(LoggingTransferListener.create()) // Listener
.source(Paths.get(filePath)) // filePath
.build();
FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);
try {
CompletedFileUpload completedFileUpload = fileUpload //
.completionFuture() // CompletableFuture<CompletedDirectoryUpload>
.join(); // Wait until completed, and return value.
//
System.out.println("SuccessfullyCompleted");
System.out.println(" --> " + completedFileUpload.toString());
} catch (CancellationException e) {
System.out.println("CancellationException");
System.out.println(" --> (It could be by the user calling the pause method.)");
} catch (CompletionException e) {
System.out.println("Completed with error: " + e);
}
}
public static void main(String[] args) {
// There are several ways to create an S3TransferManager
// @See my article 14231.
S3TransferManager transferManager = MyUtils.createS3TransferManager(MY_DO_SLUG);
//
uploadFile(transferManager, //
MY_DO_SPACES_NAME, // DigitalOcean Spaces Name.
"static/videos/sample-15s.mp4", // key
"/Volumes/New/Test/download/sample-15s.mp4" // filePath to save.
);
}
}
Output:
[main] WARN software.amazon.awssdk.transfer.s3.S3TransferManager
- The provided DefaultS3AsyncClient is not an instance of S3CrtAsyncClient, and thus multipart upload/download feature is not enabled and resumable file upload is not supported. To benefit from maximum throughput, consider using S3AsyncClient.crtBuilder().build() instead.
[main] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - Transfer initiated...
[main] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - | | 0.0%
[Thread-0] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - |====================| 100.0%
SuccessfullyCompleted
--> CompletedFileUpload(response=PutObjectResponse(ETag="044d7d8ed37e78d6537c8ab5d68b2d78"))
4. Download file với S3TransferManager
Ví dụ, download file với S3TransferManager.
S3TransferManagerDownloadExample1.java
package org.o7planning.java_14253_do_spaces.example;
import java.nio.file.Paths;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionException;
import org.o7planning.java_14253_do_spaces.utils.MyUtils;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload;
import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest;
import software.amazon.awssdk.transfer.s3.model.FileDownload;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
public class S3TransferManagerDownloadExample1 {
// DigitalOcean SLUG List:
// https://docs.digitalocean.com/products/platform/availability-matrix/
private static final String MY_DO_SLUG = "fra1";
private static final String MY_DO_SPACES_NAME = "my-do-spaces";
public static void downloadFile(S3TransferManager transferManager, String bucketName, //
String key, String filePath) {
DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder()
.getObjectRequest(req -> req.bucket(bucketName).key(key)) // bucketName & key
.destination(Paths.get(filePath))
// Attaching a LoggingTransferListener that will log the progress
.addTransferListener(LoggingTransferListener.create()).build();
FileDownload fileDownload = transferManager.downloadFile(downloadFileRequest);
try {
// Wait for the transfer to complete
CompletedFileDownload completedFileDownload = fileDownload //
.completionFuture() // CompletableFuture<CompletedFileDownload>
.join(); // Wait until completed, and return value.
//
System.out.println("SuccessfullyCompleted");
System.out.println(" --> " + completedFileDownload.toString());
} catch (CancellationException e) {
System.out.println("CancellationException");
System.out.println(" --> (It could be by the user calling the pause method.)");
} catch (CompletionException e) {
System.out.println("Completed with error: " + e);
}
}
public static void main(String[] args) {
// There are several ways to create an S3TransferManager
// @See my article 14231.
S3TransferManager transferManager = MyUtils.createS3TransferManager(MY_DO_SLUG);
//
// Test download a video file 11.9MB
//
downloadFile(transferManager, //
MY_DO_SPACES_NAME, // bucketName
"static/videos/sample-15s.mp4", // key
"/Volumes/New/Test/download/sample-15s.mp4" // filePath to save.
);
}
}
Output:
[main] WARN software.amazon.awssdk.transfer.s3.S3TransferManager
- The provided DefaultS3AsyncClient is not an instance of S3CrtAsyncClient, and thus multipart upload/download feature is not enabled and resumable file upload is not supported. To benefit from maximum throughput, consider using S3AsyncClient.crtBuilder().build() instead.
[main] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - Transfer initiated...
[aws-java-sdk-NettyEventLoop-1-2] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - | | 0.0%
[aws-java-sdk-NettyEventLoop-1-2] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - |= | 5.0%
[aws-java-sdk-NettyEventLoop-1-2] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - |== | 10.0%
..
[aws-java-sdk-NettyEventLoop-1-2] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - |================== | 90.0%
[aws-java-sdk-NettyEventLoop-1-2] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - |=================== | 95.0%
[aws-java-sdk-NettyEventLoop-1-2] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - |====================| 100.0%
SuccessfullyCompleted
--> CompletedFileDownload(response=GetObjectResponse(AcceptRanges=bytes, LastModified=2023-11-04T12:38:49Z, ContentLength=11916526, ETag="aa355e698dca652d60c0bd39931714a4", ContentType=video/mp4, Metadata={}))
[sdk-async-response-0-0] INFO software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener - Transfer complete!
5. Các ví dụ khác với S3TransferManager
Như đã đề cập DigitalOcean Spaces tương thích với Awssdk S3 API vì vậy các bài viết về Awssdk S3 dưới đây sẽ cung cấp cho bạn rất nhiều ví dụ khác. Chẳng hạn:
- Liệt kê các đối tượng trên Spaces Bucket.
- Upload một thư mục.
- Sao chép và di chuyển các đối tượng giữa các Spaces Bucket.
- ...
- Các hướng dẫn Amazon Web Services
Các hướng dẫn Amazon Web Services
- Giới thiệu về Amazon Web Services (AWS)
- Giới thiệu về Amazon S3
- Giới thiệu về Amazon Cloudfront và kiến trúc của nó
- Làm sao để giảm chi phí Amazon Cloudfront?
- Vô hiệu hoá bộ nhớ đệm CloudFront
- Giới thiệu về DigitalOcean Spaces
- Hướng dẫn tạo DigitalOcean Spaces Bucket
- Giới thiệu về Amazon ACM
- Java Awssdk S3 Tải tệp lên S3 Bucket với S3Client
- Tạo AWS accessKeyId/secretAccessKey
- Java Awssdk S3 Liệt kê các đối tượng trong S3 Bucket
- Lưu trữ (host) một Website tĩnh trên Amazon S3
- Vô hiệu hoá bộ nhớ đệm của CloudFront với Java
- Tạo DigitalOcean Spaces Access Key
- Java Awssdk Các Credentials Provider thông dụng
- Java Awssdk Tạo và sử dụng ProfileCredentialsProvider
- Java Awssdk Tạo và sử dụng EnvironmentVariableCredentialsProvider
- Java Awssdk Tạo và sử dụng SystemPropertyCredentialsProvider
- Java Awssdk S3 Tải object lên với S3TransferManager
- Java Awssdk S3 Tải object xuống với S3TransferManager
- Java thao tác với DigitalOcean Spaces sử dụng S3TransferManager
- Java tạo, liệt kê và xoá S3 Bucket
- Aws Console Tạo tài khoản người dùng IAM
- Tạo một vùng chứa Amazon S3 (S3 Bucket)
- Các quy tắc chuyển hướng cho S3 Static Website
- Cấu hình tên miền tuỳ chỉnh cho website tĩnh Amazon S3
- Tạo bản phân phối CloudFront cho S3 Bucket
- Cấu hình các trang phản hồi lỗi cho CloudFront
- Tạo các chính sách S3 Bucket
- Công cụ tạo các chính sách cho AWS - policygen
- So sánh Amazon S3 Rest API Endpoint và S3 Web Endpoint
- Chuyển hướng trong S3 Website với x-amz-website-redirect-location
- Di chuyển (migrate) dịch vụ DNS tới Amazon Route 53
- Chuyển (transfer) đăng ký tên miền tới Amazon Route 53
- Yêu cầu chứng chỉ SSL từ Amazon ACM
Show More