This is a demo of uploading files to AWS S3 using Java SpringBoot.
First, we need to add the dependency of AWS S3:
1 2 3 4 5 |
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.11.891</version> </dependency> |
Then add these configs in application.yml:
1 2 3 4 5 6 |
custom: aws: access-key: CHOBITACCESSKEY secret-key: CHOBIT/THISIS006SECRET007Key/dotORG bucket: zhyea endpoint: www.zhyea.com:80 |
The accessKey
, secretKey
and bucket
is nesscessary which can be found in aws’ admin dashboard.
Let’s create a class named AwsS3Componment
to execute uploading operation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
@Component public class AwsS3Component implements InitializingBean { @Value("${custom.aws.access-key}") private String accessKey; @Value("${custom.aws.secret-key}") private String accessSecret; @Value("${custom.aws.bucket}") private String bucket; @Value("${custom.aws.endpoint}") private String endpoint; private AmazonS3 client; @Override public void afterPropertiesSet() { ClientConfiguration config = new ClientConfiguration(); config.setProtocol(Protocol.HTTP); config.disableSocketProxy(); this.client = AmazonS3ClientBuilder .standard() .withClientConfiguration(config) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, accessSecret))) .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, Regions.CN_NORTH_1.getName())) .enablePathStyleAccess() .build(); } } |
Since my service is using endpoint, I add this line in AmazonS3Client
config:
1 |
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, Regions.CN_NORTH_1.getName())) |
Without this config, we will receive exception like this:
1 2 3 4 5 6 7 |
com.amazonaws.services.s3.model.AmazonS3Exception: The AWS Access Key Id you provided does not exist in our records. (Service: Amazon S3; Status Code: 403; Error Code: InvalidAccessKeyId; Request ID: FRDT8N0RAQFNCVDP; S3 Extended Request ID: DemEatwroXry2YN/5lyuMKDmhIi/aIz3QZPmLN0DYHeHU3oGUeOClJBcToz1J1qkcBZBfklRNs8=) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1660) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1324) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1074) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:745) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:719) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:701) |
The exception message is a little inaccurate. The exception is led by lack of endpoint config, but it remind me of invalid accessKey. It’s really obscure.
Well, next time when we get a exception about AccessKey, we can consider whether it is related to Endpoint.
If you don’t need set config of Endpoint, you must add the Region config. Then the full config is:
1 2 3 4 5 6 7 |
this.client = AmazonS3ClientBuilder .standard() .withClientConfiguration(config) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, accessSecret))) .withRegion(Regions.CN_NORTH_1) //Region onfig .enablePathStyleAccess() .build(); |
Now we have a instance of AmazonS3Client
, let’s add the code of uploading files:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * 执行文件上传 * * @param file 要上传的文件的路径 * @param key 存储文件的路径 * @return 文件路径 */ private String upload(File file, String key) { client.putObject(new PutObjectRequest(bucket, key, file).withCannedAcl(CannedAccessControlList.PublicRead)); GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucket, key); URL url = client.generatePresignedUrl(urlRequest); return url.toString(); } |
The code above uses a File
instance to upload files. However, cause of file system permissions, sometimes we need to upload files through InputStream
:
1 2 3 4 5 6 7 8 9 10 11 |
private String upload(InputStream input, String key) throws IOException { Date expireDate = new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30)); ObjectMetadata metadata = new ObjectMetadata(); metadata.setHttpExpiresDate(expireDate); metadata.setContentLength(input.available()); client.putObject(new PutObjectRequest(bucket, key, input, metadata).withCannedAcl(CannedAccessControlList.PublicRead)); GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucket, key); URL url = client.generatePresignedUrl(urlRequest); return url.toString(); } |
All!
End!