Amazon S3 (Simple Storage Service) is a cloud-based object storage service provided by Amazon Web Services (AWS). It allows developers to store and retrieve files (objects) of any size from anywhere in the world, using simple API calls.
In this article, we will explore how to perform CRUD (Create, Read, Update, Delete) operations on files stored in an S3 bucket using Spring Boot.
Prerequisites
To follow this tutorial, you will need:
Java 8 or later
Spring Boot 2.5.0 or later
An AWS account
An S3 bucket created in your AWS account
Setting Up AWS Credentials
Before we start coding, we need to set up our AWS credentials so that our Spring Boot application can access our S3 bucket.
Log in to your AWS account.
Navigate to the "IAM" service.
Click "Users" in the left-hand menu.
Click "Add user" and provide a name for the user.
Select "Programmatic access" as the access type and click "Next".
Set the permissions for the user. For this tutorial, we will give the user full access to S3. Click "Next".
Click "Create user".
Note down the Access key ID and Secret access key values that are displayed. We will use these values in our Spring Boot application.
Adding AWS SDK for Java and Spring Boot AWS Starter Dependencies
To interact with AWS S3 from our Spring Boot application, we need to add the following dependencies to our pom.xml
file:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.12.62</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.3.4</version>
</dependency>
The aws-java-sdk
dependency provides the AWS SDK for Java, which we will use to interact with S3. The spring-cloud-starter-aws
dependency provides the Spring Boot AWS starter, which sets up the AWS SDK for Java with default credentials and region.
Configuring AWS Credentials and Region
Next, we need to configure our AWS credentials and region in our Spring Boot application. We can do this by adding the following properties to our application.properties
file:
cloud.aws.credentials.accessKey=ACCESS_KEY
cloud.aws.credentials.secretKey=SECRET_KEY
cloud.aws.region.static=REGION
Next, create a new class called "S3Config" and annotate it with @Configuration
and @EnableS3
:
javaCopy code@Configuration
@EnableS3
public class S3Config {
@Value("${cloud.aws.region.static}")
private String region;
@Value("${cloud.aws.credentials.access-key}")
private String accessKey;
@Value("${cloud.aws.credentials.secret-key}")
private String secretKey;
@Bean
public AmazonS3 s3Client() {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(region)
.build();
}
}
Create Service class
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
@Service
public class S3Service {
private final AmazonS3 s3Client;
@Value("${aws.s3.bucket-name}")
private String bucketName;
public S3Service(AmazonS3 s3Client) {
this.s3Client = s3Client;
}
public List<String> listObjects() {
ObjectListing objectListing = s3Client.listObjects(bucketName);
return objectListing.getObjectSummaries()
.stream()
.map(S3ObjectSummary::getKey)
.collect(Collectors.toList());
}
public void uploadFile(MultipartFile file) throws IOException {
s3Client.putObject(new PutObjectRequest(bucketName, file.getOriginalFilename(), file.getInputStream(), null));
}
public S3Object downloadFile(String fileName) {
return s3Client.getObject(new GetObjectRequest(bucketName, fileName));
}
public void deleteFile(String fileName) {
s3Client.deleteObject(new DeleteObjectRequest(bucketName, fileName));
}
}
This service class provides methods for listing objects in the S3 bucket, uploading a file to the bucket, downloading a file from the bucket, and deleting a file from the bucket. It uses the AmazonS3 client provided by the AWS SDK to interact with the S3 service. The @Value
annotation is used to inject the bucket name from the application configuration.
Controller layer
@RestController
@RequestMapping("/s3")
public class S3Controller {
@Autowired
private S3Service s3Service;
@GetMapping("/{key}")
public ResponseEntity<byte[]> getObject(@PathVariable("key") String key) {
byte[] objectBytes = s3Service.getObject(key);
if (objectBytes != null) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(objectBytes.length);
headers.setContentDispositionFormData("attachment", key);
return new ResponseEntity<>(objectBytes, headers, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PostMapping("/{key}")
public ResponseEntity<String> createObject(@PathVariable("key") String key, @RequestBody MultipartFile file) {
try {
s3Service.createObject(key, file);
return new ResponseEntity<>("Object created successfully", HttpStatus.CREATED);
} catch (IOException e) {
return new ResponseEntity<>("Error creating object: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping("/{key}")
public ResponseEntity<String> updateObject(@PathVariable("key") String key, @RequestBody MultipartFile file) {
try {
s3Service.updateObject(key, file);
return new ResponseEntity<>("Object updated successfully", HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>("Error updating object: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/{key}")
public ResponseEntity<String> deleteObject(@PathVariable("key") String key) {
s3Service.deleteObject(key);
return new ResponseEntity<>("Object deleted successfully", HttpStatus.OK);
}
}
This controller defines endpoints for each of the CRUD operations: GET for retrieving an object, POST for creating an object, PUT for updating an object, and DELETE for deleting an object. The @GetMapping
and @PostMapping
annotations specify the URL paths for each endpoint and the @RequestBody
annotation is used to indicate that the incoming request should contain a file to be uploaded.
The controller uses the S3Service
instance to interact with Amazon S3. The getObject
method retrieves an object from S3 and returns it as a byte array. The createObject
, updateObject
, and deleteObject
methods delegate to the corresponding methods in the S3Service
instance.
Conclusion:
Spring Boot and AWS S3 provide a powerful combination for building scalable and reliable applications that require file storage and retrieval. With the help of the AWS SDK for Java and Spring Boot, it is possible to easily integrate S3 into your Spring Boot application and perform CRUD operations on S3 objects. In this article, we have covered the basics of setting up and configuring AWS S3 with Spring Boot, creating a service layer to handle CRUD operations on S3 objects, and building a REST API using Spring Boot's controller layer to interact with the service layer. By leveraging the power of AWS S3 and Spring Boot, developers can build robust and efficient applications that meet their storage needs.
I hope this helps, you!!
More such articles:
https://www.youtube.com/channel/UCiTaHm1AYqMS4F4L9zyO7qA
\==========================**=========================
If this article adds any value to you then please clap and comment.
Let’s connect on Stackoverflow, LinkedIn, & Twitter.