- Details
- Written by Nam Ha Minh
- Last Updated on 03 January 2022   |   Print Email
In this tutorial, you will learn how to integrate S3 file upload functionality into a Java web application based on Spring Boot using AWS SDK for Java - for the purpose of hosting static resources on a cloud storage service such as S3.The following picture explains the workflow of uploading files from user’s computer to Amazon S3:

Firstly, the end users choose files from their computer and submit a web form. The files will be transferred to a Spring Boot application which is running with embedded Tomcat server. And then the application uses S3 API for transferring the files to a bucket on S3 server. That means the files are transferred two times, but the process is transparent to the users.To follow this tutorial, you have to
setup AWS SDK on your computer.Technologies used: Spring framework with Spring Boot; Spring MVC; Thymeleaf and AWS SDK for Java.Software programs: Java Development Kit (JDK), Spring Tool Suite (STS) IDE.
1. Create Java Spring Boot Maven Project
Create a Spring Starter project in STS with project type is Maven and language is Java. Then update the
pom.xml file as follows:
<project... >
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.15.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
</dependencies>
</project>
As you can see, besides the Spring Boot starter dependencies required for a typical Spring MVC web application, you need to declare dependencies for AWS SDK and S3.
2. Code Upload Form
Next, let’s code a page that allows the users to pick a file for upload. Create an HTML file named
upload.html under
src/main/resources/templates directory with the following code:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring Boot File Upload to S3</title>
</head>
<body>
<div align="center">
<div><h2>Spring Boot File Upload to S3</h2></div>
<div>
<form action="upload" method="post" enctype="multipart/form-data">
<p>
Description:
<input type="text" name="description" size="30" required />
</p>
<p>
<input type="file" name="file" required />
</p>
<p>
<button type="submit">Submit</button>
</p>
</form>
</div>
</div>
</body>
</html>
At runtime, this page would look like this:

Also create the
MainController class with the following code:
package net.codejava.aws;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("")
public String viewHomePage() {
return "upload";
}
}
This is a Spring MVC controller class that implements a handler method that handles requests coming to the homepage of the application. You can see it returns the logical view name “upload” which will be resolved to the
upload.html file mentioned above.
3. Code S3 Utility Class for File Upload
Next, let’s code a utility class that uses AWS Java SDK for implementing a method that uploads a file to Amazon S3. So create the
S3Util class with the following code:
package net.codejava.aws;
import java.io.IOException;
import java.io.InputStream;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
public class S3Util {
private static final String BUCKET = "your-bucket-name";
public static void uploadFile(String fileName, InputStream inputStream)
throws S3Exception, AwsServiceException, SdkClientException, IOException {
S3Client client = S3Client.builder().build();
PutObjectRequest request = PutObjectRequest.builder()
.bucket(BUCKET)
.key(fileName)
.build();
client.putObject(request,
RequestBody.fromInputStream(inputStream, inputStream.available()));
}
}
This class will be used by the
MainController class, and you can see the code is simple and straightforward. It uses S3 API to put an object into a S3 bucket, with object’s data is read from an
InputStream object. Note that you must specify a bucket name that is available in your AWS account.
Upload File to S3 with public-read permission:
By default, the file uploaded to a bucket has read-write permission for object owner. It is not accessible for public users (everyone). If you want to give public-read access for public users, use the
acl() method as below:
PutObjectRequest request = PutObjectRequest.builder()
.bucket(BUCKET)
.key(fileName)
.acl("public-read")
.build();
Wait until the file exists:
In the code example above, the
uploadFile() method returns immediately as the put object operation is executed asynchronously. In case you want to run some custom logics that depend on the existence of the uploaded file, add the following code that waits until the file exists on S3:
S3Waiter waiter = client.waiter();
HeadObjectRequest waitRequest = HeadObjectRequest.builder()
.bucket(BUCKET)
.key(fileName)
.build();
WaiterResponse<HeadObjectResponse> waitResponse = waiter.waitUntilObjectExists(waitRequest);
waitResponse.matched().response().ifPresent(x -> {
// run custom code that should be executed after the upload file exists
});
This may cause the
uploadFile() method runs slower as it has to wait until the file exists on S3 server, and also run your custom logics.
Set additional information for the upload file:
You can use the
contentXXX() methods of the
PutObjectRequest class to specify additional information for the file stored on S3. For example, the following code set content type of the file to be “image/png” for the file:
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.acl("public-read")
.contentType("image/png")
.build();
The other methods are
contentDisposition(),
contentEncoding(),
contentLanguage(),
contentLength()…
4. Code Handler Method and Message Page
Next, update the
MainController class. Implement the second hander method that handles the submission of the upload form. Below is its complete code:
package net.codejava.aws;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class MainController {
@GetMapping("")
public String viewHomePage() {
return "upload";
}
@PostMapping("/upload")
public String handleUploadForm(Model model, String description,
@RequestParam("file") MultipartFile multipart) {
String fileName = multipart.getOriginalFilename();
System.out.println("Description: " + description);
System.out.println("filename: " + fileName);
String message = "";
try {
S3Util.uploadFile(fileName, multipart.getInputStream());
message = "Your file has been uploaded successfully!";
} catch (Exception ex) {
message = "Error uploading file: " + ex.getMessage();
}
model.addAttribute("message", message);
return "message";
}
}
As you can see, it uses the
S3Util class for transferring the uploaded file to Amazon S3, and returns the view name “message” which will be resolved to the
message.html file whose code is as below:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring Boot File Upload to S3</title>
</head>
<body>
<div align="center">
<div><h3>[[${message}]]</h3></div>
</div>
</body>
</html>
In this file, we simply use a Thymleaf expression to print value of an attribute named “message”, which is set in the controller class.
5. Test Uploading Files to Amazon S3
Run the Spring Boot project and access the URL http://localhost:8080/ in a web browser. You would see the upload page like this:

Enter some text into the description field, then choose a file and click Submit button. Wait a moment, and you will see the message page like this:

Now, sign in to your AWS account and check the bucket you used in the code. You should see the file appears there.That’s my tutorial about adding S3 file upload function to a Spring Boot application. To see the coding in action, watch the following video:
You can also download the sample project attached below.
Related AWS Java SDK Tutorials:
About the Author:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on
Facebook and watch
his Java videos on YouTube.