Στην εφαρμογή κάθε προιόν θα έχει την ίδια εικόνα σε τρία μεγέθη:
Υπάρχουν έξι κατηγορίες προιόντων :
Αρχικά, θα δημιουργήσουμε ένα φάκελο products. Μέσα στο φάκελο products, θα δημιουργήσουμε τρεις φακέλους large, small και very-small. Σε κάθε έναν από αυτούς, θα δημιουργήσουμε έξι φάκελους, fish-oils, fragrances, minerals, shampoos, superfoods και vitamins. Για να δημιουργήσουμε έναν φάκελο πατάμε Create Folder, πληκτρολογούμε το όνομα και πατάμε Save.
Το βασικό URL του bucket μας είναι το https://s3.eu-central-1.amazonaws.com/springeshop-bucket/.
Η μικρή εικόνα του προιόντος apivita-shampoo-dry-dandruff-250ml, το οποίο ανήκει στην κατηγορία σαμπούαν, βρίσκεται στο URL https://s3.eu-central-1.amazonaws.com/springeshop-bucket/products/small/shampoos/apivita-shampoo-dry-dandruff-250ml-small.jpg .
Αντίστοιχα, η μεγάλη εικόνα του προιόντος korres-fragrance-apple-blossom-100ml, το οποίο ανήκει στην κατηγορία των αρωμάτων, βρίσκεται στο URL https://s3.eu-central-1.amazonaws.com/springeshop-bucket/products/large/fragrances/korres-fragrance-apple-blossom-100ml-large.jpg .
Αρχικά, θα δημιουργήσουμε ένα package springeshop.util, το οποίο θα έχει βοηθητικές κλάσεις. Μέσα σε αυτό θα δημιουργήσουμε το enum ImageType.
package springeshop.util;
public enum ImageType {
SMALL, LARGE, VERY_SMALL
}
Στο ίδιο πακέτο θα δημιουργήσουμε μια κλάση Constants , η οποία θα περιέχει σταθερές
package springeshop.util;
public final class Constants {
private static final String AMAZON_S3_URL = "https://s3.eu-central-1.amazonaws.com/springeshop-bucket/";
private static final String SMALL_PRODUCTS_PATH = "products/small/";
private static final String LARGE_PRODUCTS_PATH = "products/large/";
private static final String VERY_SMALL_PRODUCTS_PATH = "products/very-small/";
private Constants(){}
}
Θα δημιουργήσουμε μια διεπαφή AmazonS3ClientService, η οποία περιέχει μια μέθοδο για το upload φωτογραφιών
package springeshop.service;
public interface AmazonS3ClientService {
CompletableFuture<Boolean> uploadImage(MultipartFile image, String category, ImageType imageType);
}
Η κλάση AmazonS3ClientServiceImpl θα υλοποιεί την AmazonS3ClientService. Η μέθοδος uploadImage θα κάνει το upload της εικόνας. Πρώτα μετατρέπει την εικόνα σε αρχείο File, κάνει upload την εικόνα στο κατάλληλο path και διαγράφει το αρχείο μετά. Επιστρέφει true, αν το upload ήταν επιτυχές.
package springeshop.service;
@Component
public class AmazonS3ClientServiceImpl implements AmazonS3ClientService{
private String awsS3AudioBucket
private AmazonS3 AmazonS3 amazonS3;
@Autowired
public AmazonS3ClientServiceImpl(Region awsRegion, AWSCredentialsProvider awsCredentialsProvider, String awsS3AudioBucket){
this.amazonS3 = AmazonS3ClientBuilder.standard()
.withCredentials(awsCredentialsProvider)
.withRegion(awsRegion.getName()).build();
this.awsS3AudioBucket = awsS3AudioBucket;
}
@Async
public CompletableFuture<Boolean> uploadImage(MultipartFile image, String category, ImageType imageType){
boolean isImageUploadSuccess = true;
try{
File imageFile = convertImageToFile(image);
uploadImageToS3Bucket(image.getOriginalFilename(), imageFile, category, imageType);
imageFile.delete();
}catch (IOException | AmazonServiceException ex) {
logger.error("error [" + ex.getMessage() + "] occurred while uploading [" + image.getOriginalFilename() + "] ");
isImageUploadSuccess = false;
}
return CompletableFuture.completedFuture(isImageUploadSuccess);
}
private File convertImageToFile(MultipartFile image) throws IOException{
File convertedFile = new File(image.getOriginalFilename());
FileOutputStream fileOutputStream = new FileOutputStream(convertedFile);
fileOutputStream.write(image.getBytes());
fileOutputStream.close();
return convertedFile;
}
private void uploadImageToS3Bucket(String imageName, File imageFile, String category, ImageType imageType){
if(imageType == ImageType.SMALL){
amazonS3.putObject(new PutObjectRequest(awsS3AudioBucket, Constants.SMALL_PRODUCTS_PATH + category + "/" + imageName, imageFile)
.withCannedAcl(CannedAccessControlList.PublicRead));
}else if(imageType == ImageType.LARGE){
amazonS3.putObject(new PutObjectRequest(awsS3AudioBucket, Constants.LARGE_PRODUCTS_PATH + category + "/" + imageName, imageFile)
.withCannedAcl(CannedAccessControlList.PublicRead));
}else if(imageType == ImageType.VERY_SMALL){
amazonS3.putObject(new PutObjectRequest(awsS3AudioBucket, Constants.VERY_SMALL_PRODUCTS_PATH + category + "/" + imageName, imageFile)
.withCannedAcl(CannedAccessControlList.PublicRead));
}
}
}