Spring Boot Amazon S3 - File Upload Download Delete Example



In this tutorial, we will learn how to upload, download, and delete files to/from Amazon s3 in the Spring boot project. We will develop Spring Boot REST APIs to upload, download, and delete files to/from Amazon S3.

Amazon simple storage (Amazon S3) is a service offered by Amazon web services that offer scalable, secure, and well-performing object storage.
The source code of this tutorial available on our GitHub repository at https://github.com/sourcecodeexamples/spring-boot-amazon-s3-example

Create AWS Free Account 

Before we start creating our application, head over to the Amazon console and create an account. You will be given 12 months of free access to various Amazon web services that you can use to test various Amazon services.

Create S3 Bucket

After signing up, head over to the Amazon console and search for Amazon S3 then create a new S3 bucket that we will use to store the files we will be uploading from our Spring boot application.

Name the bucket as spring-boot-amazon-storage and leave all other settings as default then create the bucket.

Access and secret keys

Create a new access key from the My Security Credentials navigation menu. Copy the access and the secret key generated as we will be using them to access the bucket from the application we will be creating.

Once we will get the following details, we will start creating our Spring boot application:
- S3 bucket
- Access and secret keys

Technologies used

  • Java 8+
  • Spring Boot
  • Spring Data JPA (Hibernate)
  • Maven
  • MySQL database
  • Lombok
  • AWS - Amazon S3
  • Eclipse STS IDE

1. Create Spring Boot Project

We’ll use Spring initializr web tool to bootstrap our application. 

Go to http://start.spring.io

Select Java in the language section.

Enter Artifact as spring-boot-amazon-s3-example

Add WebLombok, Spring Cloud AWS dependencies.

Click Generate to generate and download the project.

Once the project is generated, unzip it and import it into your favorite IDE.

2. Maven Dependencies

Open the pom.xml file and confirm below dependencies are present:
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-aws</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

3. Configure Amazon S3 Details

Open the application.yml file and add the following content to it:

cloud:
  aws:
    credentials:
      access-key: 
      secret-key: 
    region:
      static: us-east-2
    stack:
      auto: false

application:
  bucket:
    name: spring-boot-amazon-storage


spring:
  servlet:
    multipart:
      enabled: true
      file-size-threshold: 2MB
      max-file-size: 5MB
      max-request-size: 10MB

Make sure that you add Amazon S3 access and secret key in the above file.

4. S3 Storage Config Class

Let's create a configuration class to create Amazon S3 client:
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class StorageConfig {

    @Value("${cloud.aws.credentials.access-key}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secret-key}")
    private String accessSecret;
    @Value("${cloud.aws.region.static}")
    private String region;

    @Bean
    public AmazonS3 s3Client() {
        AWSCredentials credentials = new BasicAWSCredentials(accessKey, accessSecret);
        return AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(region).build();
    }

}

5. Service Layer - Upload, Download and Delete to/from Amazon S3

Let's create a StorageService class that holds all the logic to upload, download, and delete files to/from the Amazon S3 server:

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.amazonaws.util.IOUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

@Service
@Slf4j
public class StorageService {

    @Value("${application.bucket.name}")
    private String bucketName;

    @Autowired
    private AmazonS3 s3Client;

    public String uploadFile(MultipartFile file) {
        File fileObj = convertMultiPartFileToFile(file);
        String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
        s3Client.putObject(new PutObjectRequest(bucketName, fileName, fileObj));
        fileObj.delete();
        return "File uploaded : " + fileName;
    }


    public byte[] downloadFile(String fileName) {
        S3Object s3Object = s3Client.getObject(bucketName, fileName);
        S3ObjectInputStream inputStream = s3Object.getObjectContent();
        try {
            byte[] content = IOUtils.toByteArray(inputStream);
            return content;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public String deleteFile(String fileName) {
        s3Client.deleteObject(bucketName, fileName);
        return fileName + " removed ...";
    }


    private File convertMultiPartFileToFile(MultipartFile file) {
        File convertedFile = new File(file.getOriginalFilename());
        try (FileOutputStream fos = new FileOutputStream(convertedFile)) {
            fos.write(file.getBytes());
        } catch (IOException e) {
            log.error("Error converting multipartFile to file", e);
        }
        return convertedFile;
    }
}

6. REST APIs for Upload, Download, and Delete Files

Now, let's create Spring Boot REST APIs to upload, download, and delete files to/from Amazon S3:
import com.springboot.s3.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/file")
public class StorageController {

    @Autowired
    private StorageService service;

    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(@RequestParam(value = "file") MultipartFile file) {
        return new ResponseEntity<>(service.uploadFile(file), HttpStatus.OK);
    }

    @GetMapping("/download/{fileName}")
    public ResponseEntity<ByteArrayResource> downloadFile(@PathVariable String fileName) {
        byte[] data = service.downloadFile(fileName);
        ByteArrayResource resource = new ByteArrayResource(data);
        return ResponseEntity
                .ok()
                .contentLength(data.length)
                .header("Content-type", "application/octet-stream")
                .header("Content-disposition", "attachment; filename=\"" + fileName + "\"")
                .body(resource);
    }

    @DeleteMapping("/delete/{fileName}")
    public ResponseEntity<String> deleteFile(@PathVariable String fileName) {
        return new ResponseEntity<>(service.deleteFile(fileName), HttpStatus.OK);
    }
}

7. Run Spring Boot Application

We’ve successfully built all the APIs for our application. Let’s now run the app and test the APIs.

Just go to the root directory of the application and type the following command to run it -

$ mvn spring-boot:run

The application will start at Spring Boot’s default tomcat port 8080.

Source code on GitHub:

The source code of this tutorial available on our GitHub repository at https://github.com/sourcecodeexamples/spring-boot-amazon-s3-example

8. Demo

For more details and demo, you can watch this YouTube video:

Comments