Files
bflows-bandi-be/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java

196 lines
7.6 KiB
Java

package net.gepafin.tendermanagement.service.impl;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.dao.S3PathConfig;
import net.gepafin.tendermanagement.entities.DocumentEntity;
import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity;
import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum;
import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response;
import net.gepafin.tendermanagement.service.AmazonS3Service;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.apache.commons.io.FilenameUtils;
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.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Service
public class AmazonS3ServiceImpl implements AmazonS3Service {
private final Logger log = LoggerFactory.getLogger(AmazonS3ServiceImpl.class);
@Autowired
private AmazonS3 amazonS3;
@Autowired
private Environment environment;
@Value("${aws.s3.bucket.name}")
private String bucketName;
@Value("${aws.s3.url}")
private String s3Url;
@Autowired
private S3PathConfig s3ConfigBean;
@Autowired
private AmazonS3Client s3Client;
@Value("${aws.s3.region}")
private String region;
@Autowired
S3ReUploadMigrationService s3ReUploadMigrationService;
private String upload(String fileName, String s3Folder,
MultipartFile file) throws IOException {
String path = s3Folder +"/"+fileName;
InputStream inputStream = file.getInputStream();
ObjectMetadata objectMetadata = new ObjectMetadata();
Map<String, String> metadata = new HashMap<>();
metadata.put("Content-Type", file.getContentType());
metadata.put("Content-Length", String.valueOf(file.getSize()));
Optional<Map<String, String>> optionalMetaData = Optional.of(metadata);
optionalMetaData.ifPresent(map -> {
if (!map.isEmpty()) {
map.forEach(objectMetadata::addUserMetadata);
}
});
if(Boolean.FALSE.equals(isTestProfileActivated())) {
amazonS3.putObject(bucketName, path, inputStream, objectMetadata);
}
//getting actual encoded s3 file path
URL amazonS3Url = amazonS3.getUrl(bucketName, path);
String fileUrl = amazonS3Url.toString();
log.info("File '{}' uploaded successfully to Amazon S3 with URL: {}", fileName, fileUrl);
return fileUrl;
}
@Override
public Boolean delete(String s3Folder, String filePath) {
String fileName = Utils.extractFileName(filePath);
String path = s3Folder +"/"+fileName;
final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(bucketName, path);
if(Boolean.FALSE.equals(isTestProfileActivated())) {
amazonS3.deleteObject(deleteObjectRequest);
}
log.info("File '{}' deleted successfully from Amazon S3", fileName);
return true;
}
public Boolean isTestProfileActivated() {
String[] activeProfiles = environment.getActiveProfiles();
return Arrays.stream(activeProfiles).anyMatch("test"::equals);
}
@Override
public InputStream getFile(String s3Folder, String filePath) {
try {
String fileName = Utils.extractFileName(filePath);
// Decode the file name to handle special characters like '+' correctly
String decodedFileName = URLDecoder.decode(fileName, StandardCharsets.UTF_8.toString());
String path = s3Folder + "/" + decodedFileName;
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, path);
S3Object s3Object = amazonS3.getObject(getObjectRequest);
log.info("File fetched successfully from Amazon S3: {}", fileName);
return s3Object.getObjectContent();
} catch (Exception e) {
log.error("Error occurred while getting file from Amazon S3: {}", e);
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.GET_ERROR_S3));
}
}
@Override
public UploadFileOnAmazonS3Response uploadFileOnAmazonS3(String s3Folder, MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
String originalFileName = org.springframework.util.StringUtils.cleanPath(file.getOriginalFilename());
String firstNameContain = originalFileName.substring(0, originalFileName.lastIndexOf('.'));
firstNameContain = Utils.replaceSpacesWithUnderscores(firstNameContain);
firstNameContain += "_" + Utils.randomKey(7);
String fileName = (firstNameContain + "." + extension);
try {
String filepath = upload(fileName, s3Folder, file);
return UploadFileOnAmazonS3Response.builder().fileName(originalFileName).filePath(filepath).build();
} catch (Exception e) {
log.error("Error occurred while uploading file from Amazon S3: {}", e);
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3));
}
}
private String decodeS3Key(String key) {
return URLDecoder.decode(key, StandardCharsets.UTF_8);
}
@Override
public UploadFileOnAmazonS3Response moveFile(String fileName, String oldPath, String newPath) {
try {
log.info("Original Paths - oldPath: {}, newPath: {}", oldPath, newPath);
oldPath = decodeS3Key(cleanOldPath(oldPath));
newPath = cleanNewPath(oldPath, newPath);
log.info("Moving file from {} to {} in bucket {}", oldPath, newPath, bucketName);
CopyObjectRequest copyRequest = new CopyObjectRequest(bucketName, oldPath, bucketName, newPath);
s3Client.copyObject(copyRequest);
log.info("File copied successfully from {} to {}", oldPath, newPath);
s3Client.deleteObject(bucketName, oldPath);
log.info("Original file deleted successfully: {}", oldPath);
String filePath = s3Url + newPath;
return UploadFileOnAmazonS3Response.builder().fileName(fileName).filePath(filePath).build();
} catch (AmazonServiceException e) {
log.error("AWS service error while moving file: {}", e.getErrorMessage(), e);
throw e;
} catch (SdkClientException e) {
log.error("SDK client error while moving file: {}", e.getMessage(), e);
throw e;
} catch (Exception e) {
log.error("Unexpected error while moving file: {}", e.getMessage(), e);
throw e;
}
}
private String cleanNewPath(String oldPath, String newPath) {
return newPath + "/" + oldPath.substring(oldPath.lastIndexOf("/") + 1);
}
private String cleanOldPath(String oldPath) {
return oldPath.replace(s3Url, "");
}
}