395 lines
12 KiB
C#
395 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Numerics;
|
|
using System.Net;
|
|
|
|
|
|
|
|
using Amazon.DynamoDBv2.Model;
|
|
using Amazon.DynamoDBv2;
|
|
using Amazon.S3;
|
|
using Amazon.Internal;
|
|
using Amazon;
|
|
using Amazon.S3.Model;
|
|
using Amazon.Runtime.Internal;
|
|
|
|
|
|
|
|
namespace ServerCore;
|
|
|
|
|
|
// HANDOVER: AWS S3 SDK Wrapper 클래스 이다.
|
|
// S3 저장소에 관리할 Bucket 정보를 관리해 준다.
|
|
|
|
public abstract class S3ConnectorBase
|
|
{
|
|
private AmazonS3Client? m_s3_client;
|
|
|
|
private string m_access_key = string.Empty;
|
|
private string m_secret_key = string.Empty;
|
|
private string m_region = string.Empty;
|
|
|
|
public bool createS3Client(string accessKey, string secretKey, string region)
|
|
{
|
|
try
|
|
{
|
|
m_access_key = accessKey;
|
|
m_secret_key = secretKey;
|
|
m_region = region;
|
|
|
|
var regionEndpoint = RegionEndpoint.GetBySystemName(region);
|
|
|
|
// 여기서 실제로 연결 시도는 하지 않는다 !!!, 단순 초기화
|
|
m_s3_client = new AmazonS3Client(accessKey, secretKey, regionEndpoint);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().error($"Exception !!!, Failed to perform in createS3Client() : accessKey:{accessKey}, secretKey:{secretKey}, region:{region}, exception:{e}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<(bool, List<S3Bucket>)> getBuckets()
|
|
{
|
|
var buckets = new List<S3Bucket>();
|
|
|
|
try
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
var response = await m_s3_client.ListBucketsAsync();
|
|
if (response.HttpStatusCode != HttpStatusCode.OK)
|
|
{
|
|
Log.getLogger().fatal($"Failed to ListBucketsAsync() !!! : HttpStatusCode:{response.HttpStatusCode}");
|
|
return (false, buckets);
|
|
}
|
|
|
|
return (true, response.Buckets);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perfrom in getBuckets() !!! : exception:{e}");
|
|
}
|
|
|
|
return (false, buckets);
|
|
}
|
|
|
|
public async Task<bool> createBucket(PutBucketRequest request)
|
|
{
|
|
try
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
var response = await m_s3_client.PutBucketAsync(request);
|
|
if (response.HttpStatusCode != HttpStatusCode.OK)
|
|
{
|
|
Log.getLogger().fatal($"Failed to PutBucketAsync() !!! : HttpStatusCode:{response.HttpStatusCode}");
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perfrom in createBucket() !!! : exception:{e}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> uploadFile(PutObjectRequest request)
|
|
{
|
|
try
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
var response = await m_s3_client.PutObjectAsync(request);
|
|
if (response.HttpStatusCode != HttpStatusCode.OK)
|
|
{
|
|
Log.getLogger().fatal($"Failed to PutObjectAsync() !!! : HttpStatusCode:{response.HttpStatusCode}");
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in uploadFile() : exception:{e}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> deleteFile(DeleteObjectRequest request)
|
|
{
|
|
try
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
var response = await m_s3_client.DeleteObjectAsync(request);
|
|
if (response.HttpStatusCode != HttpStatusCode.NoContent)
|
|
{
|
|
Log.getLogger().fatal($"Failed to DeleteObjectAsync() !!!, in deleteFile() : HttpStatusCode:{response.HttpStatusCode}");
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in deleteFile() : exception:{e}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> deleteFolderFile(ListObjectsV2Request request)
|
|
{
|
|
try
|
|
{
|
|
ListObjectsV2Response response;
|
|
|
|
do
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
response = await m_s3_client.ListObjectsV2Async(request);
|
|
if (response.HttpStatusCode != HttpStatusCode.OK)
|
|
{
|
|
Log.getLogger().fatal($"Failed to ListObjectsV2Async() !!!, in deleteFolderFile() : HttpStatusCode:{response.HttpStatusCode}");
|
|
return false;
|
|
}
|
|
|
|
if (response.S3Objects.Count == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var delete_request = new DeleteObjectsRequest
|
|
{
|
|
BucketName = request.BucketName,
|
|
};
|
|
|
|
foreach (var s3_object in response.S3Objects)
|
|
{
|
|
delete_request.AddKey(s3_object.Key);
|
|
}
|
|
|
|
var delete_response = await m_s3_client.DeleteObjectsAsync(delete_request);
|
|
if (response.HttpStatusCode != HttpStatusCode.OK)
|
|
{
|
|
Log.getLogger().fatal($"Failed to DeleteObjectsAsync() !!!, in deleteFolderFile() : HttpStatusCode:{response.HttpStatusCode}");
|
|
return false;
|
|
}
|
|
|
|
request.ContinuationToken = response.NextContinuationToken;
|
|
}
|
|
while (response.IsTruncated);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in deleteFolderFile() : exception:{e}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<(bool, Stream?)> getFileStream(GetObjectRequest request)
|
|
{
|
|
try
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
var response = await m_s3_client.GetObjectAsync(request);
|
|
if (response.HttpStatusCode != HttpStatusCode.OK)
|
|
{
|
|
Log.getLogger().fatal($"Failed to GetObjectAsync() !!! : HttpStatusCode:{response.HttpStatusCode}");
|
|
return (false, null);
|
|
}
|
|
|
|
return (true, response.ResponseStream);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in getFileStream() : exception:{e}");
|
|
}
|
|
|
|
return (false, null);
|
|
}
|
|
|
|
private async Task<(bool, string)> generatePreSignedUrl(GetPreSignedUrlRequest request)
|
|
{
|
|
try
|
|
{
|
|
NullReferenceCheckHelper.throwIfNull(m_s3_client, () => $"m_s3_client is null !!!");
|
|
|
|
var presigned_url = await m_s3_client.GetPreSignedURLAsync(request);
|
|
|
|
return (true, presigned_url);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in generatePresignedUrl() : exception:{e}");
|
|
}
|
|
|
|
return (false, string.Empty);
|
|
}
|
|
|
|
public async Task<bool> createBucketIfNotExist(string bucketName)
|
|
{
|
|
if (false == await isExistBucket(bucketName))
|
|
{
|
|
var request = new PutBucketRequest
|
|
{
|
|
BucketName = bucketName,
|
|
UseClientRegion = true,
|
|
|
|
};
|
|
|
|
if (false == await createBucket(request))
|
|
{
|
|
var err_msg = $"Failed to createBucket() !!! : bucketName:{bucketName}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> isExistBucket(string bucketName)
|
|
{
|
|
(var is_success, var buckets) = await getBuckets();
|
|
if (false == is_success)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (var bucket in buckets)
|
|
{
|
|
if (bucket.BucketName == bucketName) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public async Task<bool> tryUploadFile(string bucketName, string s3Key, string data)
|
|
{
|
|
var err_msg = string.Empty;
|
|
|
|
using (var memory_stream = data.toStream())
|
|
{
|
|
var request = new PutObjectRequest
|
|
{
|
|
BucketName = bucketName,
|
|
Key = s3Key,
|
|
InputStream = memory_stream,
|
|
};
|
|
|
|
if (false == await uploadFile(request))
|
|
{
|
|
err_msg = $"Failed to uploadFile() !!!, in tryUploadFile() : bucketName:{bucketName}, s3Key:{s3Key}";
|
|
Log.getLogger().error(err_msg);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> tryDeleteFile(string bucketName, string s3Key)
|
|
{
|
|
var request = new DeleteObjectRequest
|
|
{
|
|
BucketName = bucketName,
|
|
Key = s3Key,
|
|
};
|
|
|
|
if (false == await deleteFile(request))
|
|
{
|
|
var err_msg = $"Failed to deleteFile() !!!, in tryDeleteFile() : bucketName:{bucketName}, s3Key:{s3Key}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> tryDeleteFolderFile(string bucketName, string prefix)
|
|
{
|
|
var request = new ListObjectsV2Request
|
|
{
|
|
BucketName = bucketName,
|
|
Prefix = prefix,
|
|
};
|
|
|
|
if (false == await deleteFolderFile(request))
|
|
{
|
|
var err_msg = $"Failed to deleteFolderFile() !!!, in tryDeleteFolderFile() : bucketName:{bucketName}, prefix:{prefix}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<(bool, string)> tryGetFileData(string bucketName, string s3Key)
|
|
{
|
|
var request = new GetObjectRequest
|
|
{
|
|
BucketName = bucketName,
|
|
Key = s3Key,
|
|
};
|
|
|
|
(var is_success, var stream) = await getFileStream(request);
|
|
if (false == is_success)
|
|
{
|
|
var err_msg = $"Failed to getFile() !!! - bucketName:{bucketName}, s3Key:{s3Key}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (false, string.Empty);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(stream, () => $"stream is null !!! - bucketName:{bucketName}, s3Key:{s3Key}");
|
|
|
|
return (true, stream.toString());
|
|
}
|
|
|
|
public async Task<(bool, string)> getPresignedUrl( string bucketName, string s3Key
|
|
, HttpVerb verbType, DateTime toExpireTime )
|
|
{
|
|
var err_msg = string.Empty;
|
|
|
|
var request = new GetPreSignedUrlRequest
|
|
{
|
|
BucketName = bucketName,
|
|
Key = s3Key,
|
|
Verb = verbType,
|
|
Expires = toExpireTime
|
|
};
|
|
|
|
(var is_success, var presigned_url) = await generatePreSignedUrl(request);
|
|
if(false == is_success)
|
|
{
|
|
err_msg = $"Failed to generatePreSignedUrl() !!! : bucketName:{bucketName}, s3Key:{s3Key}, httpVerbType:{verbType}, toExpireTime:{toExpireTime.toStringWithUtcIso8601()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (false, presigned_url);
|
|
}
|
|
|
|
return (true, presigned_url);
|
|
}
|
|
|
|
public AmazonS3Client? getAmazonS3Client() => m_s3_client;
|
|
|
|
|
|
public string toBasicString()
|
|
{
|
|
return $"{this.getTypeName()}, AccessKey:{m_access_key}, SecretKey:{m_secret_key}, Region:{m_region}";
|
|
}
|
|
}
|