Spring Boot 2.7.10, JDK 1.8 기준
implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.238')
implementation 'com.amazonaws:aws-java-sdk-s3'
app:
ncloud:
accessKey: {accessKey}
secretKey: {secretKey}
objectStorage:
endPoint: "https://kr.object.ncloudstorage.com"
regionName: "{regionName}"
bucketName: "{bucketName}"
@Data
class FileInfoVO {
private String fileUrl;
private String fileName;
}
@Slf4j
public class FileService {
@Value("${app.ncloud.accessKey}")
private String accessKey;
@Value("${app.ncloud.secretKey}")
private String secretKey;
@Value("${app.ncloud.objectStorage.endPoint}")
private String endPoint;
@Value("${app.ncloud.objectStorage.regionName}")
private String regionName;
@Value("${app.ncloud.objectStorage.bucketName}")
private String bucketName;
/**
* object storage에서 파일 다운로드
* @param param 다운로드할 객체 정보
*/
public ResponseEntity<byte[]> fileDownload(FileInfoVO param) throws AmazonS3Exception, IOException {
byte[] bytes = null;
HttpHeaders httpHeaders = null;
try {
final AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, regionName))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
S3Object s3Object = null;
s3Object = s3.getObject(bucketName, param.getFileUrl());
S3ObjectInputStream s3ObjectInputStream = s3Object.getObjectContent();
bytes = IOUtils.toByteArray(s3ObjectInputStream);
httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentLength(bytes.length);
String encFileName = URLEncoder.encode(param.getFileName(), "UTF-8").replaceAll("\\+", "%20");
httpHeaders.setContentDispositionFormData("attachment", encFileName);
s3ObjectInputStream.close();
}catch (Exception e){
throw e;
}
return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
}
/**
* object storage에서 파일 다운로드 (zip 형태로 압축해서 내려줌)
* 하드에 저장하는 방식이 아니라 빠른 속도 및 파일관리 불필요
* @param param 다운로드할 객체 정보들
*/
public ResponseEntity<byte[]> fileDownloadAll(List<FileInfoVO> param) throws AmazonS3Exception, IOException {
List<byte[]> bytes = new ArrayList<>();
try {
final AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, regionName))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
if(param.size() <= 0) {
throw new NullPointerException();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
for(int i = 0; i < param.size(); i++) {
S3Object s3Object = s3.getObject(bucketName, param.get(i).getFileUrl());
S3ObjectInputStream s3ObjectInputStream = s3Object.getObjectContent();
byte[] a = IOUtils.toByteArray(s3ObjectInputStream);
bytes.add(a);
s3ObjectInputStream.close();
String fileName = param.get(i).fileName;
ZipEntry entry = new ZipEntry(fileName);
entry.setSize(bytes.get(i).length);
entry.setTime(System.currentTimeMillis());
zos.putNextEntry(entry);
zos.write(bytes.get(i));
zos.closeEntry();
}
try {
zos.finish();
zos.flush();
zos.close();
} catch(Exception e) {
log.error(StringUtils.getStackTrace(e));
}finally {
if(zos != null){
zos.close();
}
}
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"download.zip\"")
.contentLength(baos.size())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(baos.toByteArray());
}catch (IOException e){
throw e;
}catch (Exception e){
throw e;
}
}
/**
* 파일 업로드
* @param files MultipartFile
*/
public boolean fileUpload(MultipartFile[] files) throws Exception {
final AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, regionName))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
String folderName = "{서버에 저장할 파일 경로}";
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(0L);
objectMetadata.setContentType("application/x-directory");
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, folderName, new ByteArrayInputStream(new byte[0]), objectMetadata);
try {
s3.putObject(putObjectRequest);
} catch (AmazonS3Exception e) {
log.error("Error : {}", e.getMessage());
} catch(SdkClientException e) {
log.error("Error : {}", e.getMessage());
}
for(MultipartFile file : files) {
String fileName = folderName + "{파일 이름}";
try {
s3.putObject(new PutObjectRequest(bucketName, fileName, file.getInputStream(), null));
}catch (IOException e){
log.error(e.getMessage());
return false;
}catch (Exception e){
log.error(e.getMessage());
return false;
}
}
return true;
}
/**
* 업로드된 파일 삭제
* @param param 파일정보
*/
public boolean deleteFile(FileInfoVO param) throws Exception {
final AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, regionName))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
try {
s3.deleteObject(bucketName, param.getFileUrl()); // 물리파일삭제
return true;
} catch (AmazonS3Exception e) {
log.error("Error : {}", e.getMessage());
return false;
} catch(SdkClientException e) {
log.error("Error : {}", e.getMessage());
return false;
}
}
}