Amazon S3 + Angular 6 HttpClient + SpringBoot - Upload/Download Files/Images Example
Tags: angular, amazons3, springboot
Published: 2021-03-11 11:16:01

https://grokonez.com/frontend/angular/angular-6/angular-6-springboot-amazon-s3-upload-download-files-images-example

Amazon Simple Storage Service (Amazon S3) is object storage built to store and retrieve any amount of data from web or mobile. Amazon S3 is designed to scale computing easier for developers. In the tutorial, we show how to build an Angular 6 App Client to upload/download files/images to/from Amazon S3 with Spring Boot RestApi Server.

Related posts:
– <a href="https://grokonez.com/aws/amazon-s3/amazon-s3-springboot-restapis-upload-download-file-image-to-s3">Amazon S3 – SpringBoot RestAPIs Upload/Download File/Image to S3</a>
– <a href="https://grokonez.com/spring-framework/spring-boot/amazon-s3-springboot-restapis-list-all-files-in-s3-bucket">Amazon S3 – SpringBoot RestAPIs List All Files in S3 Bucket</a>
- <a href="https://grokonez.com/java-integration/angular-6-upload-get-multipartfile-spring-boot-example">Angular 6 – Upload/Get MultipartFile to/from Spring Boot Server</a>

<!--more-->
<h2>Technologies</h2>
– Angular 6
– Java 1.8
– Spring Boot 2.0.4.RELEASE
– Maven 3.3.9
– Spring Tool Suite 3.9.0.RELEASE
- Amazon S3
<h2>Demo</h2>
<iframe width="853" height="480" src="https://www.youtube.com/embed/UQ7xnELIuq4?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<h2>Overview</h2>
<h3>Spring Boot Server</h3>
We expose 3 RestAPIs:

<ul>
<li><code>@PostMapping("/api/file/upload")</code></li>
<li><code>@GetMapping("/api/file/{keyname}")</code></li>
<li><code>@GetMapping("/api/file/all")</code></li>
</ul>

<img src="https://grokonez.com/wp-content/uploads/2018/08/angular-6-spring-boot-amazon-s3-upload-download-files-springboot-project.png" alt="angular-6-spring-boot-amazon-s3-upload-download-files + springboot project" width="306" height="272" class="alignnone size-full wp-image-14024" />

– For init an AmazonS3 client, we use:

<pre><code class="language-java">
BasicAWSCredentials awsCreds = new BasicAWSCredentials(awsId, awsKey);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
			.withRegion(Regions.fromName(region))
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.build();
</code></pre>

– For upload S3 objects, we use:

<pre><code class="language-java">
public PutObjectResult putObject(
            String bucketName, String key, InputStream input, ObjectMetadata metadata)
            throws SdkClientException, AmazonServiceException;
</code></pre>

– For download S3 objects, we use:

<pre><code class="language-java">
public S3Object getObject(GetObjectRequest getObjectRequest)
            throws SdkClientException, AmazonServiceException;
</code></pre>
<h3>Angular 6 App Client</h3>

<img src="https://grokonez.com/wp-content/uploads/2018/08/angular-6-spring-boot-amazon-s3-upload-download-files-angular-project.png" alt="angular-6-spring-boot-amazon-s3-upload-download-files + angular project" width="232" height="414" class="alignnone size-full wp-image-14025" />

– <code>upload-file.service</code> provides methods: push File to Storage and get Files.
– <code>list-upload.component</code> gets and displays list of Files.
– <code>form-upload.component</code> helps upload File.
– <code>details-upload.component</code> is detail for each item in list of Files

<img src="https://grokonez.com/wp-content/uploads/2018/08/angular-6-spring-boot-amazon-s3-upload-download-files-angular-component-overview.png" alt="angular-6-spring-boot-amazon-s3-upload-download-files + angular-component-overview" width="440" height="407" class="alignnone size-full wp-image-14026" />
<h2>Practice</h2>
<h3>SpringBoot Server</h3>
<h4>Create SprigBoot Project</h4>
We use SpringToolSuite to create SpringBoot project with needed dependencies:

<pre><code class="language-xhtml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
	&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.amazonaws&lt;/groupId&gt;
    &lt;artifactId&gt;aws-java-sdk&lt;/artifactId&gt;
    &lt;version&gt;1.11.379&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
<h4>Configure Amazon Client</h4>
<code>S3Config.java</code> ->

<pre><code class="language-java">
package com.grokonez.s3.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 
@Configuration
public class S3Config {
	@Value("${gkz.aws.access_key_id}")
	private String awsId;
 
	@Value("${gkz.aws.secret_access_key}")
	private String awsKey;
	
	@Value("${gkz.s3.region}")
	private String region;

	@Bean
	public AmazonS3 s3client() {
		
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(awsId, awsKey);
		AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
								.withRegion(Regions.fromName(region))
		                        .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
		                        .build();
		
		return s3Client;
	}
}</code></pre>

In <code>application.properties</code>, add <code>aws</code> configuration:

<pre>
gkz.aws.access_key_id=// change to your access_key_id
gkz.aws.secret_access_key=// change to your secret_access_key
gkz.s3.bucket=grokonez-s3-bucket
gkz.s3.region=us-east-2
</pre>
<h4>S3 Upload/Download Service</h4>
Interface <code>S3Services.java</code> ->

<pre><code class="language-java">
package com.grokonez.s3.services;

import java.io.ByteArrayOutputStream;
import java.util.List;

import org.springframework.web.multipart.MultipartFile;

public interface S3Services {
	public ByteArrayOutputStream downloadFile(String keyName);
	public void uploadFile(String keyName, MultipartFile file);
	public List<String> listFiles();
}</code></pre>

Implementation <code>S3ServicesImpl.java</code> ->

<pre><code class="language-java">
package com.grokonez.s3.services.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.grokonez.s3.services.S3Services;
 
@Service
public class S3ServicesImpl implements S3Services {
	
	private Logger logger = LoggerFactory.getLogger(S3ServicesImpl.class);
	
	@Autowired
	private AmazonS3 s3client;
 
	@Value("${gkz.s3.bucket}")
	private String bucketName;
 
	@Override
	public ByteArrayOutputStream downloadFile(String keyName) {
		try {
            S3Object s3object = s3client.getObject(new GetObjectRequest(bucketName, keyName));
            
            InputStream is = s3object.getObjectContent();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int len;
            byte[] buffer = new byte[4096];
            while ((len = is.read(buffer, 0, buffer.length)) != -1) {
                baos.write(buffer, 0, len);
            }
            
            return baos;
		} catch (IOException ioe) {
			logger.error("IOException: " + ioe.getMessage());
        } catch (AmazonServiceException ase) {
        	logger.info("sCaught an AmazonServiceException from GET requests, rejected reasons:");
			logger.info("Error Message:    " + ase.getMessage());
			logger.info("HTTP Status Code: " + ase.getStatusCode());
			logger.info("AWS Error Code:   " + ase.getErrorCode());
			logger.info("Error Type:       " + ase.getErrorType());
			logger.info("Request ID:       " + ase.getRequestId());
			throw ase;
        } catch (AmazonClientException ace) {
        	logger.info("Caught an AmazonClientException: ");
            logger.info("Error Message: " + ace.getMessage());
            throw ace;
        }
		
		return null;
	}
 
	@Override
	public void uploadFile(String keyName, MultipartFile file) {
		try {
			ObjectMetadata metadata = new ObjectMetadata();
			metadata.setContentLength(file.getSize());
			s3client.putObject(bucketName, keyName, file.getInputStream(), metadata);
		} catch(IOException ioe) {
			logger.error("IOException: " + ioe.getMessage());
		} catch (AmazonServiceException ase) {
			logger.info("Caught an AmazonServiceException from PUT requests, rejected reasons:");
			logger.info("Error Message:    " + ase.getMessage());
			logger.info("HTTP Status Code: " + ase.getStatusCode());
			logger.info("AWS Error Code:   " + ase.getErrorCode());
			logger.info("Error Type:       " + ase.getErrorType());
			logger.info("Request ID:       " + ase.getRequestId());
			throw ase;
        } catch (AmazonClientException ace) {
            logger.info("Caught an AmazonClientException: ");
            logger.info("Error Message: " + ace.getMessage());
            throw ace;
        }
	}
	
	public List<String> listFiles() {
		
	  ListObjectsRequest listObjectsRequest = 
              new ListObjectsRequest()
                    .withBucketName(bucketName);
                    //.withPrefix("test" + "/");
		
		List<String> keys = new ArrayList<>();
		
		ObjectListing objects = s3client.listObjects(listObjectsRequest);
		
		while (true) {
			List<S3ObjectSummary> summaries = objects.getObjectSummaries();
			if (summaries.size() < 1) {
				break;
			}
			
			for (S3ObjectSummary item : summaries) {
	            if (!item.getKey().endsWith("/"))
	            	keys.add(item.getKey());
	        }
			
			objects = s3client.listNextBatchOfObjects(objects);
		}
		
		return keys;
	}
}</code></pre>

More at: https://grokonez.com/frontend/angular/angular-6/angular-6-springboot-amazon-s3-upload-download-files-images-example