How to Upload Xml File as a New Object to Aws S3 Java Sdk
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 become over how to upload files into Amazon S3 using Jump Boot.
Prerequisites
- Some knowledge in Java and Leap Boot.
- Java development kit installed on your estimator.
- Your favourite IDE. I use Intellij customs edition which is gratis.
Amazon spider web services business relationship
Earlier we start creating our application, head over to Amazon console, and create an account. You lot will exist given 12 months of gratis access to diverse Amazon web services that you tin can use to test diverse Amazon services.
Subsequently signing up, head over to Amazon console and search for Amazon S3 in the search box provided in the console.
Amazon S3 bucket
Afterwards selecting Amazon S3 from the pace above, create a new S3 saucepan that nosotros will employ to store the files nosotros will exist uploading from our application.
Proper name the bucket as spring-amazon-storage
and go out all other settings as default so create the bucket.
Access and secret keys
Create a new access key from My Security Credentials
navigation carte du jour as shown in the image beneath. Copy the access and the cloak-and-dagger key generated as nosotros will be using them to access the bucket from the application we will be creating.
Creating the application
We will be using spring initializr to create our awarding. Head over to spring initializr and create a new Spring Boot application adding h2
, spring boot dev tools
, spring data jpa
and jump web
as dependencies then generate the project.
Unzip the downloaded project and open up it in your favorite IDE.
Adding Amazon SDK dependency
Amazon SDK makes it possible to collaborate with various Amazon services from our applications. In the pom.xml
file add the Amazon SDK dependency as shown below.
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk</artifactId> <version>1.11.931</version> </dependency>
Project structure
config/ |--- AmazonConfig.coffee |--- BucketName.java controllers/ |--- TodoController.java domain/ |--- Todo.java repositories/ |--- TodoRepository.java service/ |--- FileStore.java |--- TodoService.coffee |--- TodoServiceImpl.coffee SpringAmazonApplication.coffee
Configuration bundle
In the configuration package, we take 2 Java files, i that authenticates with Amazon S3 and the other which contains the bucket name.
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.notation.Configuration; @Configuration public class AmazonConfig { @Bean public AmazonS3 s3 () { AWSCredentials awsCredentials = new BasicAWSCredentials( "accessKey" , "secretKey" ); render AmazonS3ClientBuilder . standard () . withRegion ( "ap-south-i" ) . withCredentials ( new AWSStaticCredentialsProvider(awsCredentials)) . build (); } }
The AmazonConfig
course in a higher place is annotated with @Configuration
annotation to make it bachelor to the Spring context every bit a configuration class. With the Amazon credentials we got from the Amazon console earlier we volition 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 final String bucketName; }
In the BucketName
enum above we pass in the bucket proper name that we created in the Amazon console earlier. The bucket will be used to store all of our file uploads.
-
@AllArgsConstructor
annotation generates a constructor with thebucketName
variable in the enum. -
@Getter
annotation 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.
@Information @AllArgsConstructor @NoArgsConstructor @Architect @Entity public form Todo { @Id @GeneratedValue private Long id; private Cord title; private String description; individual String imagePath; private String imageFileName; }
-
@Data
notation generatesgetters
,setters
,toString
andequals
methods for theTodo
class. -
@AllArgsConstructor
annotation 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 design for theTodo
course. -
@Entity
annotation makes theTodo
class a database entity. -
@Id
annotation marks theid
field as a master key in the database. -
@GeneratedValue
annotation makes theid
field auto-increase whenever a newtodo
is saved into the database.
Repository package
In this bundle, we have the repository grade 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 parcel
@AllArgsConstructor @Service public course FileStore { private final AmazonS3 amazonS3; public void upload (Cord path, String fileName, Optional<Map<String, Cord>> optionalMetaData, InputStream inputStream) { ObjectMetadata objectMetadata = new ObjectMetadata(); optionalMetaData. ifPresent (map -> { if (!map. isEmpty ()) { map. forEach (objectMetadata::addUserMetadata); } }); effort { 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 key) { try { S3Object object = amazonS3. getObject (path, key); S3ObjectInputStream objectContent = object. getObjectContent (); return IOUtils. toByteArray (objectContent); } catch (AmazonServiceException | IOException e) { throw new IllegalStateException( "Failed to download the file" , e); } } }
In the FileStore
class above, we take the logic used to upload and download files from Amazon S3.
In the upload
method we pass in:
-
path
is the path on the Amazon S3 saucepan where the file volition be stored. -
fileName
is the bodily name of the file being uploaded. Information technology will be 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 exist saved to Amazon S3.
ObjectMetadata objectMetadata = new ObjectMetadata(); optionalMetaData. ifPresent (map -> { if (!map. isEmpty ()) { map. forEach (objectMetadata::addUserMetadata); } });
The in a higher place lawmaking 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, key);
downloads the file from the path passed in and with the file proper name similar to the primal 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 can be sent over Restful APIs.
public interface TodoService { Todo saveTodo (Cord title, String clarification, MultipartFile file); byte [] downloadTodoImage (Long id); List<Todo> getAllTodos (); }
The TodoService
interface in a higher place contains various methods that nosotros 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 clarification, MultipartFile file) { //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 prototype" ); } //get file metadata Map<String, String> metadata = new HashMap<>(); metadata. put ( "Content-Type" , file. getContentType ()); metadata. put ( "Content-Length" , Cord. valueOf (file. getSize ())); //Salve Epitome in S3 and then relieve Todo in the database Cord path = Cord. format ( "%s/%s" , BucketName. TODO_IMAGE . getBucketName (), UUID. randomUUID ()); String fileName = String. format ( "%s" , file. getOriginalFilename ()); try { fileStore. upload (path, fileName, Optional. of (metadata), file. getInputStream ()); } grab (IOException e) { throw new IllegalStateException( "Failed to upload file" , e); } Todo todo = Todo. architect () . description (clarification) . 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 (); render fileStore. download (todo. getImagePath (), todo. getImageFileName ()); } @Override public Listing<Todo> getAllTodos () { Listing<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 parcel
In this parcel, we accept TodoController
class which handles the incoming HTTP requests.
@RestController @RequestMapping ( "api/v1/todo" ) @AllArgsConstructor @CrossOrigin ( "*" ) public class TodoController { TodoService service; @GetMapping public ResponseEntity<Listing<Todo>> getTodos () { render 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 championship, @RequestParam ( "description" ) Cord description, @RequestParam ( "file" ) MultipartFile file) { return new ResponseEntity<>(service. saveTodo (title, 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 bucket
Decision
Congratulations! Now that you learned how to upload and download files from Amazon S3, get ahead and implement the logic for uploading multiple files to Amazon S3.
Observe the source code hither.
Happy Coding!
Peer Review Contributions by: Linus Muema
Source: https://www.section.io/engineering-education/spring-boot-amazon-s3/
0 Response to "How to Upload Xml File as a New Object to Aws S3 Java Sdk"
Post a Comment