openplanning

Java Awssdk S3 Tải tệp lên S3 Bucket với S3Client

  1. Thư viện
  2. Upload file lên S3Bucket với S3Client
  3. Upload Stream, String, byte[]
  4. Object Metadata
  5. Object Tags
  6. Redirect URL
  7. Ví dụ S3Waiter
  8. Object Retention
Trong Java Awssdk S3, có hai cách để bạn upload file lên trên S3 Bucket đó là sử dụng S3Client hoặc S3TransferManager.
S3Client
S3Client cung cấp một cách cơ bản để truyền các đối tượng đến và đi từ Amazon S3 với hiệu suất và độ tin cậy cao, nó sử dụng "Multipart Upload API" (API tải lên nhiều phần) và "byte-range fetches" (tìm nạp theo phạm vi byte) của Amazon AWS.
S3TransferManager
S3TransferManager là một tiện ích truyền tải cấp cao được xây dựng dựa trên S3Client. Nó cung cấp một API đơn giản để cho phép bạn truyền tệp và thư mục giữa ứng dụng của bạn và Amazon S3.
S3TransferManager cũng cho phép bạn theo dõi tiến trình truyền trong thời gian thực cũng như tạm dừng quá trình truyền để thực hiện sau đó.
Trong bài viết này tôi sẽ hướng dẫn bạn sử dụng S3Client để tải các file lên S3 Bucket và các ví dụ khác có liên quan.
Trước hết chúng ta tạo lớp MyUtils với phương thức tiện ích để tạo ra đối tượng S3Client, nó được sử dụng trong các ví dụ của bài viết này.
MyUtils.java
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

public class MyUtils {  

	public static S3Client createS3Client(Region region) {
		AwsCredentials credentials = AwsBasicCredentials.create("accessKeyId", "secretAccessKey");
		AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(credentials);

		S3Client client = S3Client.builder() //
				.credentialsProvider(credentialsProvider) //
				.region(region) //
				.build();

		return client;
	} 
}
Để tạo đối tượng S3Client bạn cần phải tạo một đối tượng AwsCredentialsProvider, đối tượng này cung cấp thông tin xác thực (Credentials) cho phép bạn tương tác với AWS. Xem thêm bài viết dưới đây để tạo một AwsCredentialsProvider phù hợp với mục đích sử dụng của bạn.

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>

<!-- 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. Upload file lên S3Bucket với S3Client

Một ví dụ đơn giản sử dụng S3Client tải một file lên S3 Bucket.
S3ClientUploadExample1.java
package org.o7planning.java_14201_awssdk_s3;

import java.io.File;

import org.o7planning.awssdks3.utils.MyUtils;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

public class S3ClientUploadExample1 {
	// EU (Frankfurt) - Germany.
	private static final Region myRegion = Region.EU_CENTRAL_1;
	private static final String bucketName = "test1.o7planning.org";

	public static void main(String[] args) {
		S3Client s3Client = MyUtils.createS3Client(myRegion);

		PutObjectRequest putObject = PutObjectRequest.builder() //
				.bucket(bucketName) //
				.key("statics/images/sample.png") //
				.build();

		File localFile = new File("/Volumes/New/Test/pngFile.png");

		// This example uses RequestBody.fromFile
		// to avoid loading the whole file into memory.
		s3Client.putObject(putObject, RequestBody.fromFile(localFile));

		System.out.println("Done!");
	}
}
Trong trường hợp Bucket của bạn được bật ACL, bạn có thể quản lý quyền truy cập tới từng đối tượng riêng lẻ. Chẳng hạn, thiết lập quyền đọc công khai đối với một đối tượng:
PutObjectRequest putObject = PutObjectRequest.builder() //
		.bucket(bucketName) //
		.key("statics/images/sample.png") //
		.acl(ObjectCannedACL.PUBLIC_READ) // (**)
		.build();
Xem thêm bài viết về ACL để biết cách nó hoạt động.
  • AWS S3 ACL

3. Upload Stream, String, byte[]

Bạn cũng có thể upload String, byte[] hoặc một Stream có độ dài xác định trước lên S3 Bucket. Hãy xem các phương thức "Factory" tĩnh của lớp RequestBody dưới đây:
RequestBody static methods
public static RequestBody fromInputStream(InputStream inputStream, long contentLength)  
public static RequestBody fromString(String contents, Charset cs) 
public static RequestBody fromString(String contents)  
public static RequestBody fromBytes(byte[] bytes)  
public static RequestBody fromByteBuffer(ByteBuffer byteBuffer) 
public static RequestBody fromRemainingByteBuffer(ByteBuffer byteBuffer)  
public static RequestBody empty()  
public static RequestBody fromContentProvider(ContentStreamProvider provider, long contentLength, String mimeType)  
public static RequestBody fromContentProvider(ContentStreamProvider provider, String mimeType)   
Ví dụ, upload một String thành một đối tượng trên S3 Bucket:
PutObjectRequest putObject = PutObjectRequest.builder() //
		.bucket(bucketName) //
		.key("readme.txt") // 
		.build();

RequestBody dataToUpload = RequestBody.fromString("Some Content..."); 
s3Client.putObject(putObject, dataToUpload); 

4. Object Metadata

Khi upload một đối tượng lên S3 Bucket với S3Client bạn có thể thiết lập Metadata cho đối tượng này.
Theo quy ước, các Metadata do người dùng định nghĩa phải có tiếp đầu ngữ "x-amz-meta-", chẳng hạn:
  • x-amz-meta-myval-1
  • x-amz-meta-myval-2
S3ClientUploadMetadataExample1.java
package org.o7planning.java_14201_awssdk_s3;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.o7planning.awssdks3.utils.MyUtils;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

public class S3ClientUploadMetadataExample1 {
	// EU (Frankfurt) - Germany.
	private static final Region myRegion = Region.EU_CENTRAL_1;
	private static final String bucketName = "test1.o7planning.org";

	public static void main(String[] args) {
		S3Client s3Client = MyUtils.createS3Client(myRegion);

		Map<String, String> userMetaData = new HashMap<>();
		userMetaData.put("x-amz-meta-myVal", "A Test Value");

		PutObjectRequest putObject = PutObjectRequest.builder() //
				.bucket(bucketName) //
				.key("statics/images/sample2.png") //
				.metadata(userMetaData) //
				.build();

		File localFile = new File("/Volumes/New/Test/pngFile.png");

		// This example uses RequestBody.fromFile
		// to avoid loading the whole file into memory.
		s3Client.putObject(putObject, RequestBody.fromFile(localFile));

		System.out.println("Upload Done!\n");

		showMetadatas(s3Client);
	}

	private static void showMetadatas(S3Client s3Client) {
		HeadObjectRequest headObjectRequest = HeadObjectRequest.builder() //
				.bucket(bucketName).key("statics/images/sample2.png")//
				.build();

		HeadObjectResponse headObjectResponse = s3Client.headObject(headObjectRequest); 
		System.out.println("Content Type: " + headObjectResponse.contentType()); 
		Map<String, String> userDefineMetadatas = headObjectResponse.metadata();

		userDefineMetadatas.forEach((k, v) -> {
			System.out.println(k + " : " + v);
		});
	}
}
Output:
Upload Done!

Content Type: image/png
myval : A Test Value
Kết quả nhìn thấy trên S3 Bucket:

5. Object Tags

"TAGS" là các thông tin bổ xung được gắn trên một đối tượng, mỗi TAG là một cặp giá trị và mỗi đối tượng được phép có tối đa 10 cặp giá trị như vậy.
  • Object Tag là gì trong Amazon S3?
S3ClientUploadTagsExample.java
package org.o7planning.java_14201_awssdk_s3;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.o7planning.awssdks3.utils.MyUtils;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest;
import software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.Tag;
import software.amazon.awssdk.services.s3.model.Tagging;

public class S3ClientUploadTagsExample {
	private static final Region myRegion = Region.EU_CENTRAL_1;
	private static final String bucketName = "test1.o7planning.org";

	public static void main(String[] args) {
		S3Client s3Client = MyUtils.createS3Client(myRegion);

		Tag authorTag = Tag.builder() //
				.key("author").value("Smith").build();

		Tag languageTag = Tag.builder() //
				.key("language").value("English").build();

		List<Tag> tags = new ArrayList<>();
		tags.add(authorTag);
		tags.add(languageTag);

		Tagging tagging = Tagging.builder().tagSet(tags).build();

		PutObjectRequest putObject = PutObjectRequest.builder() //
				.bucket(bucketName) //
				.key("java/java-tutorial.pdf") //
				.tagging(tagging) //
				.build();

		File localFile = new File("/Volumes/New/Test/Java-Tutorial.pdf");

		s3Client.putObject(putObject, RequestBody.fromFile(localFile));
		System.out.println("Upload Done!\n");

		showTags(s3Client);
	}

	private static void showTags(S3Client s3Client) {
		GetObjectTaggingRequest request = GetObjectTaggingRequest.builder() //
				.bucket(bucketName) //
				.key("java/java-tutorial.pdf") //
				.build();

		GetObjectTaggingResponse response = s3Client.getObjectTagging(request);
		List<Tag> tags = response.tagSet();

		tags.forEach(tag -> {
			System.out.println(tag.key() + " : " + tag.value());
		});
	}
}
Output:
Upload Done!

author : Smith
language : English
Kết quả nhìn thấy trên S3 Bucket:

6. Redirect URL

Nếu tính năng Website tĩnh được bật trong Bucket của bạn, các đối tượng có thể được truy cập thông qua một URL. Bạn cũng có thể thiết lập để URL của một đối tượng chuyển hướng (redirect) đến một URL khác.
  • URL: https://yourdomain.com/article/java-tutorial-old
  • ---> https://yourdomain.com/article/java-tutorial-new
S3ClientUploadRedirectExample1.java
package org.o7planning.java_14201_awssdk_s3;

import org.o7planning.awssdks3.utils.MyUtils;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

public class S3ClientUploadRedirectExample1 {
	// EU (Frankfurt) - Germany.
	private static final Region myRegion = Region.EU_CENTRAL_1;
	private static final String bucketName = "test1.o7planning.org";

	public static void main(String[] args) {
		S3Client s3Client = MyUtils.createS3Client(myRegion);

		PutObjectRequest putObject = PutObjectRequest.builder() //
				.bucket(bucketName) //
				.key("article/java-tutorial-old") //
				.websiteRedirectLocation("/article/java-tutorial-new") //
				.build();

		// Upload Empty Data
		s3Client.putObject(putObject, RequestBody.empty());

		System.out.println("Done!");
	}
}
Sau khi chạy ví dụ trên, bạn có thể thấy kết quả trên S3 Bucket:
  • Object Key: article/java-tutorial-old
  • Metadata Key: x-amz-website-redirect-location
  • Metadata Value: /article/java-tutorial-new
URL của đối tượng cũng có thể chuyển hướng tới một URL bên ngoài (Của một website khác).
PutObjectRequest putObject = PutObjectRequest.builder() //
		.bucket(bucketName) //
		.key("go/digitalocean/promotion") //
		.websiteRedirectLocation("https://m.do.co/c/9fdc6836d334") //
		.build();

7. Ví dụ S3Waiter

Nếu bạn đang upload một đối tượng trên Thread-1, và Thread-2 đang chờ đợi đối tượng này xuất hiện trên Bucket. Hãy sử dụng S3Waiter trong Thread-2.
S3WaiterExample1.java
package org.o7planning.java_14201_awssdk_s3;

import java.io.File;

import org.o7planning.awssdks3.utils.MyUtils;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.waiters.S3Waiter;

public class S3WaiterExample1 {
	// EU (Frankfurt) - Germany.
	private static final Region myRegion = Region.EU_CENTRAL_1;
	private static final String bucketName = "test1.o7planning.org";

	private static String objectKey = "statics/videos/sample-15s.mp4";

	public static void main(String[] args) {
		MyUploadThread uploadThread = new MyUploadThread();
		uploadThread.start();

		SubscriberThread subscriberThread = new SubscriberThread();
		subscriberThread.start();
	}

	static class MyUploadThread extends Thread {
		@Override
		public void run() {
			S3Client s3Client = MyUtils.createS3Client(myRegion);

			PutObjectRequest putObject = PutObjectRequest.builder() //
					.bucket(bucketName) //
					.key(objectKey) //
					.build();
			System.out.println("Upload a Video 11.7MB (MyUploadThread)");

			// A Video 11.7MB
			File localFile = new File("/Volumes/New/Test/sample-15s.mp4");

			// This example uses RequestBody.fromFile
			// to avoid loading the whole file into memory.
			s3Client.putObject(putObject, RequestBody.fromFile(localFile));

			System.out.println("Upload Done! (MyUploadThread)");
		}
	}

	static class SubscriberThread extends Thread {
		@Override
		public void run() {
			S3Client s3Client = MyUtils.createS3Client(myRegion);

			System.out.println("Wait until video exists! (SubscriberThread)");
			S3Waiter waiter = s3Client.waiter();
			HeadObjectRequest requestWait = HeadObjectRequest.builder() //
					.bucket(bucketName) //
					.key(objectKey) //
					.build();

			WaiterResponse<HeadObjectResponse> waiterResponse = waiter.waitUntilObjectExists(requestWait);

			waiterResponse.matched().response().ifPresent(System.out::println);
		}
	}
}
Output:
Wait until video exists! (SubscriberThread)
Upload a Video 11.7MB (MyUploadThread)
Upload Done! (MyUploadThread)
HeadObjectResponse(AcceptRanges=bytes, LastModified=2023-11-11T08:08:16Z, ContentLength=11916526, ETag="aa355e698dca652d60c0bd39931714a4", ContentType=video/mp4, ServerSideEncryption=AES256, Metadata={})
  • Java Awssdk S3 S3Waiter

8. Object Retention

"Object Retention" là một đối tượng được bảo hộ tạm thời trong một khoảng thời gian được thiết lập. Trong suốt thời gian nó được bảo hộ bạn không thể sửa đổi hoặc xoá nó. Nói cách khác, "Object Retention" là đối tượng "Write-Once-Read-Many (WORM)" (Ghi một lần đọc nhiều lần).
S3Client cho phép tải lên các đối tượng với tính năng "Retention" với điều kiện S3 Bucket phải được bật chế độ "Object Lock". Nếu bạn quan tâm có thể xem chi tiết hơn trong bài viết dưới đây:
  • Java Awssdk S3 Object Retention

Các hướng dẫn Amazon Web Services

Show More