How to We Upload Files in S3 Bucket in Aws From Java Code
Amazon simple storage (Amazon S3) is a service offered by Amazon web services that offers scalable, secure, and well performing object storage. This article will get over how to upload files into Amazon S3 using Spring Boot.
Prerequisites
- Some knowledge in Coffee and Spring Boot.
- Java development kit installed on your computer.
- Your favourite IDE. I utilise Intellij community edition which is free.
Amazon web services account
Before we start creating our awarding, head over to Amazon console, and create an account. You will be given 12 months of complimentary access to various Amazon web services that you lot can use to test various Amazon services.
After signing up, head over to Amazon panel and search for Amazon S3 in the search box provided in the console.
Amazon S3 bucket
After selecting Amazon S3 from the step in a higher place, create a new S3 bucket that nosotros will utilize to store the files we volition exist uploading from our application.
Proper noun the saucepan equally spring-amazon-storage
and leave all other settings as default and so create the bucket.
Access and secret keys
Create a new access key from My Security Credentials
navigation menu as shown in the image below. Copy the admission and the hugger-mugger key generated equally we will be using them to access the bucket from the awarding we will be creating.
Creating the application
Nosotros will be using spring initializr to create our awarding. Head over to spring initializr and create a new Spring Boot application calculation h2
, spring kicking dev tools
, spring information jpa
and spring web
every bit dependencies then generate the project.
Unzip the downloaded project and open it in your favorite IDE.
Calculation Amazon SDK dependency
Amazon SDK makes it possible to interact with various Amazon services from our applications. In the pom.xml
file add the Amazon SDK dependency as shown below.
<!-- https://mvnrepository.com/antiquity/com.amazonaws/aws-java-sdk --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk</artifactId> <version>1.xi.931</version> </dependency>
Project construction
config/ |--- AmazonConfig.coffee |--- BucketName.java controllers/ |--- TodoController.java domain/ |--- Todo.java repositories/ |--- TodoRepository.java service/ |--- FileStore.java |--- TodoService.coffee |--- TodoServiceImpl.java SpringAmazonApplication.java
Configuration package
In the configuration package, we have 2 Java files, ane that authenticates with Amazon S3 and the other which contains the bucket proper noun.
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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public form AmazonConfig { @Bean public AmazonS3 s3 () { AWSCredentials awsCredentials = new BasicAWSCredentials( "accessKey" , "secretKey" ); return AmazonS3ClientBuilder . standard () . withRegion ( "ap-south-1" ) . withCredentials ( new AWSStaticCredentialsProvider(awsCredentials)) . build (); } }
The AmazonConfig
class in a higher place is annotated with @Configuration
annotation to make it bachelor to the Spring context every bit a configuration course. With the Amazon credentials we got from the Amazon panel earlier nosotros will authenticate to S3 using the AmazonS3ClientBuilder
bachelor in the Amazon-SDK that we added to our pom.xml
ealier.
import lombok.AllArgsConstructor; import lombok.Getter; @AllArgsConstructor @Getter public enum BucketName { TODO_IMAGE( "spring-amazon-storage" ); private final String bucketName; }
In the BucketName
enum above we pass in the bucket name that nosotros created in the Amazon console before. The saucepan will be used to store all of our file uploads.
-
@AllArgsConstructor
annotation generates a constructor with thebucketName
variable in the enum. -
@Getter
notation generates a getter for thebucketName
variable in the enum.
Domain package
In this bundle we have the Todo
model that represents our Todo
in the database.
@Data @AllArgsConstructor @NoArgsConstructor @Builder @Entity public course Todo { @Id @GeneratedValue private Long id; private String title; private String clarification; private Cord imagePath; individual String imageFileName; }
-
@Data
annotation generatesgetters
,setters
,toString
andequals
methods for theTodo
class. -
@AllArgsConstructor
note generates a constructor with all the arguments for theTodo
class. -
@NoArgsConstructor
annotation generates a constructor with no arguments for theTodo
class. -
@Builder
annotation creates a builder blueprint for theTodo
course. -
@Entity
note makes theTodo
course a database entity. -
@Id
notation marks theid
field as a primary primal in the database. -
@GeneratedValue
annotation makes theid
field auto-increase whenever a newtodo
is saved into the database.
Repository package
In this package, we have the repository class that extends the JPA CrudRepository
interface that makes it possible to perform various database queries.
public interface TodoRepository extends CrudRepository<Todo, Long> { Todo findByTitle (String championship); }
Service package
@AllArgsConstructor @Service public class FileStore { private final AmazonS3 amazonS3; public void upload (String path, Cord fileName, Optional<Map<String, String>> optionalMetaData, InputStream inputStream) { ObjectMetadata objectMetadata = new ObjectMetadata(); optionalMetaData. ifPresent (map -> { if (!map. isEmpty ()) { map. forEach (objectMetadata::addUserMetadata); } }); endeavor { amazonS3. putObject (path, fileName, inputStream, objectMetadata); } take hold of (AmazonServiceException e) { throw new IllegalStateException( "Failed to upload the file" , e); } } public byte [] download (String path, String central) { try { S3Object object = amazonS3. getObject (path, cardinal); S3ObjectInputStream objectContent = object. getObjectContent (); return IOUtils. toByteArray (objectContent); } grab (AmazonServiceException | IOException eastward) { throw new IllegalStateException( "Failed to download the file" , east); } } }
In the FileStore
course above, we have the logic used to upload and download files from Amazon S3.
In the upload
method we laissez passer in:
-
path
is the path on the Amazon S3 bucket where the file will be stored. -
fileName
is the bodily name of the file being uploaded. It will exist used as the cardinal when downloading the file from S3. -
optionalMetaData
map contains the details of the file i.e file type and file size. -
inputStream
contains the actual file that should be saved to Amazon S3.
ObjectMetadata objectMetadata = new ObjectMetadata(); optionalMetaData. ifPresent (map -> { if (!map. isEmpty ()) { map. forEach (objectMetadata::addUserMetadata); } });
The above code block loops through the optionalMetaData
map adding all of the file information to the S3 objectMetaData
.
-
amazonS3.putObject(path, fileName, inputStream, objectMetadata);
saves the file to Amazon S3 bucket.
In the download
method:
-
S3Object object = amazonS3.getObject(path, cardinal);
downloads the file from the path passed in and with the file proper noun similar to the key passed in thegetObject
method. -
S3ObjectInputStream objectContent = object.getObjectContent();
gets an inputStream from the object returned from Amazon S3. -
IOUtils.toByteArray(objectContent)
converts the input stream tobyteArray
that tin be sent over Restful APIs.
public interface TodoService { Todo saveTodo (Cord title, String clarification, MultipartFile file); byte [] downloadTodoImage (Long id); Listing<Todo> getAllTodos (); }
The TodoService
interface above contains various methods that we will implement to exist able to save and get todos
.
@Service @AllArgsConstructor public class TodoServiceImpl implements TodoService { private terminal FileStore fileStore; private final TodoRepository repository; @Override public Todo saveTodo (String title, String description, MultipartFile file) { //cheque if the file is empty if (file. isEmpty ()) { throw new IllegalStateException( "Cannot upload empty file" ); } //Check if the file is an image if (!Arrays. asList (IMAGE_PNG. getMimeType (), IMAGE_BMP. getMimeType (), IMAGE_GIF. getMimeType (), IMAGE_JPEG. getMimeType ()). contains (file. getContentType ())) { throw new IllegalStateException( "FIle uploaded is not an image" ); } //get file metadata Map<String, String> metadata = new HashMap<>(); metadata. put ( "Content-Blazon" , file. getContentType ()); metadata. put ( "Content-Length" , String. valueOf (file. getSize ())); //Salve Image in S3 and then save Todo in the database String path = String. format ( "%s/%s" , BucketName. TODO_IMAGE . getBucketName (), UUID. randomUUID ()); Cord fileName = String. format ( "%s" , file. getOriginalFilename ()); try { fileStore. upload (path, fileName, Optional. of (metadata), file. getInputStream ()); } catch (IOException eastward) { throw new IllegalStateException( "Failed to upload file" , e); } Todo todo = Todo. builder () . description (description) . title (title) . imagePath (path) . imageFileName (fileName) . build (); repository. save (todo); render repository. findByTitle (todo. getTitle ()); } @Override public byte [] downloadTodoImage (Long id) { Todo todo = repository. findById (id). get (); return fileStore. download (todo. getImagePath (), todo. getImageFileName ()); } @Override public List<Todo> getAllTodos () { List<Todo> todos = new ArrayList<>(); repository. findAll (). forEach (todos::add together); return todos; } }
In the TodoServiceImpl
to a higher place, we provide the implementation for the methods for saving and getting all todos
.
Controllers package
In this package, we have TodoController
class which handles the incoming HTTP requests.
@RestController @RequestMapping ( "api/v1/todo" ) @AllArgsConstructor @CrossOrigin ( "*" ) public class TodoController { TodoService service; @GetMapping public ResponseEntity<List<Todo>> getTodos () { return new ResponseEntity<>(service. getAllTodos (), HttpStatus. OK ); } @PostMapping ( path = "" , consumes = MediaType. MULTIPART_FORM_DATA_VALUE , produces = MediaType. APPLICATION_JSON_VALUE ) public ResponseEntity<Todo> saveTodo ( @RequestParam ( "title" ) String title, @RequestParam ( "description" ) String clarification, @RequestParam ( "file" ) MultipartFile file) { render new ResponseEntity<>(service. saveTodo (title, clarification, file), HttpStatus. OK ); } @GetMapping (value = "{id}/image/download" ) public byte [] downloadTodoImage ( @PathVariable ( "id" ) Long id) { return service. downloadTodoImage (id); } }
Testing our uploads and downloads from the S3 bucket
Conclusion
Congratulations! Now that you learned how to upload and download files from Amazon S3, go alee and implement the logic for uploading multiple files to Amazon S3.
Observe the source code here.
Happy Coding!
Peer Review Contributions past: Linus Muema
manifoldscerfumfor57.blogspot.com
Source: https://www.section.io/engineering-education/spring-boot-amazon-s3/
0 Response to "How to We Upload Files in S3 Bucket in Aws From Java Code"
Post a Comment