Uploading a File to S3 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 volition become over how to upload files into Amazon S3 using Spring Boot.

Prerequisites

  • Some knowledge in Java and Spring Kick.
  • Java development kit installed on your figurer.
  • Your favourite IDE. I use Intellij customs edition which is free.

Amazon web services account

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

Later signing up, head over to Amazon console and search for Amazon S3 in the search box provided in the console.

Amazon search console

Amazon S3 bucket

Later selecting Amazon S3 from the step in a higher place, create a new S3 bucket that nosotros volition use to store the files we will be uploading from our awarding.

Amazon creating S3 bucket

Name the bucket equally spring-amazon-storage and get out all other settings as default then create the saucepan.

Admission and surreptitious keys

Create a new access key from My Security Credentials navigation menu as shown in the prototype below. Copy the admission and the hugger-mugger primal generated as we will be using them to admission the bucket from the application nosotros will be creating.

Amazon secret key

Creating the awarding

We will exist using spring initializr to create our application. Head over to spring initializr and create a new Bound Kick application calculation h2, leap boot dev tools, spring data jpa and spring web as dependencies then generate the project.

Spring Boot create application

Unzip the downloaded project and open information technology 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 beneath.

                          <!-- https://mvnrepository.com/antiquity/com.amazonaws/aws-coffee-sdk -->              <dependency>              <groupId>com.amazonaws</groupId>              <artifactId>aws-java-sdk</artifactId>              <version>one.11.931</version>              </dependency>                      

Project structure

            config/ |--- AmazonConfig.java |--- BucketName.java controllers/ |--- TodoController.java domain/ |--- Todo.java repositories/ |--- TodoRepository.java service/ |--- FileStore.java |--- TodoService.java |--- TodoServiceImpl.java SpringAmazonApplication.coffee                      

Configuration bundle

In the configuration packet, we take two Java files, 1 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              {              @Edible bean              public              AmazonS3              s3              ()              {              AWSCredentials awsCredentials              =              new              BasicAWSCredentials(              "accessKey"              ,              "secretKey"              );              return              AmazonS3ClientBuilder              .              standard              ()              .              withRegion              (              "ap-due south-1"              )              .              withCredentials              (              new              AWSStaticCredentialsProvider(awsCredentials))              .              build              ();              }              }                      

The AmazonConfig course above is annotated with @Configuration annotation to brand it available to the Jump context as a configuration class. With the Amazon credentials we got from the Amazon console earlier we will authenticate to S3 using the AmazonS3ClientBuilder available 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              last              Cord bucketName;              }                      

In the BucketName enum above we laissez passer in the bucket proper noun that nosotros created in the Amazon console earlier. The saucepan will be used to store all of our file uploads.

  • @AllArgsConstructor annotation generates a constructor with the bucketName variable in the enum.
  • @Getter annotation generates a getter for the bucketName variable in the enum.

Domain packet

In this package nosotros have the Todo model that represents our Todo in the database.

                          @Information              @AllArgsConstructor              @NoArgsConstructor              @Builder              @Entity              public              course              Todo              {              @Id              @GeneratedValue              private              Long id;              private              String title;              individual              String description;              private              String imagePath;              individual              Cord imageFileName;              }                      
  • @Information annotation generates getters, setters, toString and equals methods for the Todo class.
  • @AllArgsConstructor notation generates a constructor with all the arguments for the Todo grade.
  • @NoArgsConstructor annotation generates a constructor with no arguments for the Todo class.
  • @Builder annotation creates a architect pattern for the Todo class.
  • @Entity annotation makes the Todo course a database entity.
  • @Id annotation marks the id field as a primary key in the database.
  • @GeneratedValue annotation makes the id field motorcar-increment whenever a new todo is saved into the database.

Repository package

In this bundle, we have the repository form 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 title);              }                      

Service package

                          @AllArgsConstructor              @Service              public              class              FileStore              {              individual              final              AmazonS3 amazonS3;              public              void              upload              (Cord path,              Cord fileName,              Optional<Map<Cord,              String>>              optionalMetaData,              InputStream inputStream)              {              ObjectMetadata objectMetadata              =              new              ObjectMetadata();              optionalMetaData.              ifPresent              (map              ->              {              if              (!map.              isEmpty              ())              {              map.              forEach              (objectMetadata::addUserMetadata);              }              });              try              {              amazonS3.              putObject              (path,              fileName,              inputStream,              objectMetadata);              }              catch              (AmazonServiceException east)              {              throw              new              IllegalStateException(              "Failed to upload the file"              ,              e);              }              }              public              byte              []              download              (String path,              String key)              {              try              {              S3Object object              =              amazonS3.              getObject              (path,              key);              S3ObjectInputStream objectContent              =              object.              getObjectContent              ();              return              IOUtils.              toByteArray              (objectContent);              }              catch              (AmazonServiceException              |              IOException due east)              {              throw              new              IllegalStateException(              "Failed to download the file"              ,              e);              }              }              }                      

In the FileStore class to a higher place, we take the logic used to upload and download files from Amazon S3.

In the upload method nosotros laissez passer in:

  • path is the path on the Amazon S3 bucket where the file will be stored.
  • fileName is the actual proper noun of the file beingness uploaded. It will be used every bit the fundamental when downloading the file from S3.
  • optionalMetaData map contains the details of the file i.e file blazon and file size.
  • inputStream contains the bodily 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 name like to the key passed in the getObject method.
  • S3ObjectInputStream objectContent = object.getObjectContent(); gets an inputStream from the object returned from Amazon S3.
  • IOUtils.toByteArray(objectContent) converts the input stream to byteArray that can be sent over Restful APIs.
                          public              interface              TodoService              {              Todo              saveTodo              (Cord title,              String description,              MultipartFile file);              byte              []              downloadTodoImage              (Long id);              Listing<Todo>              getAllTodos              ();              }                      

The TodoService interface above contains various methods that we will implement to be able to save and get todos.

                          @Service              @AllArgsConstructor              public              class              TodoServiceImpl              implements              TodoService              {              private              final              FileStore fileStore;              private              final              TodoRepository repository;              @Override              public              Todo              saveTodo              (String title,              String description,              MultipartFile file)              {              //bank check 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"              );              }              //become file metadata                                          Map<String,              String>              metadata              =              new              HashMap<>();              metadata.              put              (              "Content-Type"              ,              file.              getContentType              ());              metadata.              put              (              "Content-Length"              ,              String.              valueOf              (file.              getSize              ()));              //Save Image in S3 then salvage Todo in the database                                          String path              =              String.              format              (              "%south/%s"              ,              BucketName.              TODO_IMAGE              .              getBucketName              (),              UUID.              randomUUID              ());              String fileName              =              String.              format              (              "%southward"              ,              file.              getOriginalFilename              ());              try              {              fileStore.              upload              (path,              fileName,              Optional.              of              (metadata),              file.              getInputStream              ());              }              take hold of              (IOException e)              {              throw              new              IllegalStateException(              "Failed to upload file"              ,              east);              }              Todo todo              =              Todo.              builder              ()              .              description              (description)              .              title              (championship)              .              imagePath              (path)              .              imageFileName              (fileName)              .              build              ();              repository.              salvage              (todo);              return              repository.              findByTitle              (todo.              getTitle              ());              }              @Override              public              byte              []              downloadTodoImage              (Long id)              {              Todo todo              =              repository.              findById              (id).              go              ();              render              fileStore.              download              (todo.              getImagePath              (),              todo.              getImageFileName              ());              }              @Override              public              List<Todo>              getAllTodos              ()              {              List<Todo>              todos              =              new              ArrayList<>();              repository.              findAll              ().              forEach              (todos::add);              return              todos;              }              }                      

In the TodoServiceImpl above, nosotros provide the implementation for the methods for saving and getting all todos.

Controllers parcel

In this bundle, we have TodoController course 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"              )              Cord title,              @RequestParam              (              "description"              )              String clarification,              @RequestParam              (              "file"              )              MultipartFile file)              {              return              new              ResponseEntity<>(service.              saveTodo              (championship,              description,              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 saucepan

Amazon S3 upload

Conclusion

Congratulations! Now that you lot learned how to upload and download files from Amazon S3, go ahead and implement the logic for uploading multiple files to Amazon S3.

Find the source code here.

Happy Coding!


Peer Review Contributions by: Linus Muema

albersdersecting.blogspot.com

Source: https://www.section.io/engineering-education/spring-boot-amazon-s3/

0 Response to "Uploading a File to S3 Java Code"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel