Spring  Boot + AWS S3 CRUD operations

Spring Boot + AWS S3 CRUD operations

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.

  1. Log in to your AWS account.

  2. Navigate to the "IAM" service.

  3. Click "Users" in the left-hand menu.

  4. Click "Add user" and provide a name for the user.

  5. Select "Programmatic access" as the access type and click "Next".

  6. Set the permissions for the user. For this tutorial, we will give the user full access to S3. Click "Next".

  7. Click "Create user".

  8. 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://medium.com/techwasti

https://www.youtube.com/channel/UCiTaHm1AYqMS4F4L9zyO7qA

https://www.techwasti.com/

\==========================**=========================

If this article adds any value to you then please clap and comment.

Let’s connect on Stackoverflow, LinkedIn, & Twitter.

Did you find this article valuable?

Support techwasti by becoming a sponsor. Any amount is appreciated!