Object storage에 파일 조회하고 업로드하는 방법에 대해 알아봅니다.

 

 

 

0. 사전 준비.

 

AWS S3든 뭐든 오브젝트 스토리지를 준비합니다. 단, AWS SDK를 사용할 예정이기 때문에 S3 Compatible 한 오브젝트 스토리지를 준비해야 합니다. 

 

만약 준비된 오브젝트 스토리지가 없다면 다음 글을 참고해 Minio를 준비해 봅시다.

2020/10/21 - [Programming] - [MINIO] 시놀로지 NAS에서 MINIO를 이용해 오브젝트 스토리지 구성하기

2020/10/23 - [Programming] - [Minio] Minio Object Stroage에 Region 지정하기.

 

[Minio] Minio Object Stroage에 Region 지정하기.

Minio Object Stroage에 Region 지정하는 방법에 대해 알아봅니다. 0. 사전 준비. 미리 Minio를 준비합니다. Minio 설치 방법은 다음 글을 참고해 주세요: 2020/10/21 - [Programming] - [MINIO] 시놀로지 NAS에..

smoh.tistory.com

 

IDE는 Visual Studio 2019 CE를 사용하였으며 AST.NET Core 버전은 3.0을 사용했습니다.

 

 

 

1. 솔루션 및 프로젝트 생성.

 

VS를 열고 새 프로젝트를 생성합니다. C# - ASP.NET Core 웹 애플리케이션을 선택합니다.

 

 

프로젝트 탬플릿은 API를 선택합니다. 

 

 

디버그를 시작해 시작화면을 확인합니다. 기본적으로 자동 생성되는 컨트롤러인 WeatherForecast 컨트롤러에서 데이터를 보여주고 있을 겁니다.

 

 

 

2. Nuget 패키지 추가하기.

 

S3 compatible Object Storage를 사용하므로 우선 ASW SDK를 설치해 줍니다. Nuget을 통해 AWSSDK.Core와 AWSSDK.S3를 먼저 설치해 줍니다. 그리고 추후 구현할 파일 리스트 조회를 위해 Json 관련 패키지도 같이 설치해 줍니다.

 

 

 

 

3. 컨트롤러 추가 및 파일 업로드 구현.

 

프로젝트를 우클릭해 컨트롤러를 추가합니다. "읽기/쓰기 작업이 포함된 api 컨트롤러 클래스"를 선택하면 기본인 예시 GET/POST/DELETE 메서드가 추가되어 있습니다. 어차피 새로 코딩해야 하니 "API 컨트롤러 클래스 - 비어있음"을 선택해 컨트롤러를 생성해 줍니다.

 

ASP.NET Core 코드에 대해선 자세히 설명하지 않도록 하겠습니다. 우선 S3 Client를 생성하고 POST로 업로드를 하는 메서드를 만들어보겠습니다.

 

using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using Microsoft.AspNetCore.Mvc;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace S3StorageManager.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class S3FileController : ControllerBase
    {
        private const string _storageEndpoint = "https://your.host.here";
        private const string _accessKeyId = "youraccesskeyidhere";
        private const string _secretAccessKey = "yoursecretaccesskeyhere";
        private readonly AmazonS3Config _s3Config = new AmazonS3Config()
        {
            RegionEndpoint = RegionEndpoint.APNortheast2,
            ServiceURL = _storageEndpoint,
            ForcePathStyle = true
        };

        [HttpPost("upload")]
        public async Task<ActionResult> Upload()
        {
            var req = HttpContext.Request;
            var form = req.Form;
            string fileName = form["filename"];
            string bucketName = form["bucketname"];
            try
            {
                using (var client = new AmazonS3Client(_accessKeyId, _secretAccessKey, _s3Config))
                {
                    using (var ms = new MemoryStream())
                    {
                        form.Files.First().CopyTo(ms);
                        var uploadReq = new TransferUtilityUploadRequest();
                        uploadReq.InputStream = ms;
                        uploadReq.Key = fileName;
                        uploadReq.BucketName = bucketName;
                        uploadReq.CannedACL = S3CannedACL.PublicRead;
                        var fileTransferUtil = new TransferUtility(client);
                        await fileTransferUtil.UploadAsync(uploadReq);
                        return Ok();
                    }
                }
            }
            catch(Exception e)
            {
                return StatusCode(500, e.Message);
            }
        }
    }
}

 

소스코드를 위에서부터 찬찬히 봅시다. 먼저 Endpoint, AccessKeyId, SecretAccessKey를 지정해 줍니다.

그리고 S3 Client를 위한 Config를 생성합니다. _s3Config의 RegionEndpoint는 S3의 Region을 의미합니다. 앞서 지정한 Minio Storage의 Region을 입력해 주세요. ServiceURL은 Endpoint를 의미합니다. 우리는 아마존의 S3 경로를 사용하지 않기 때문에 Minio의 Endpoint값을 입력해 줍니다. ForcePathStyle은 AWS SDK로 Minio를 개발하기 위해 반드시 True값으로 설정되어 있어야 합니다.

 

POST로 upload요청이 오면 Upload가 호출됩니다. 먼저 요청의 form으로부터 저장될 파일 이름과 버킷 이름을 받아옵니다. 그 후 미리 정의한 키값들과 설정값으로 S3 Client를 만든 뒤 MemoryStream에 form내의 파일을 복사합니다. 그 후 업로드 요청에 파일, 파일 이름, 버킷 이름을 지정한 뒤 UploadAync로 파일 업로드를 시도합니다.

 

바로 테스트를 시도해 봅시다. 먼저 코드를 실행시킨 뒤 Postman과 같은 프로그램을 이용해서 POST 요청을 날려봅시다.

 

 

위와 같이 POST 요청을 준비합니다. 엔드포인트는 호스트, 디버그 포트, 컨트롤러를 이용해 자신의 환경에 맞게 수정해 줍니다. filename은 버킷에 저장될 파일의 이름이고 bucketname은 파일이 저장될 버킷의 이름입니다. file은 아무거나 업로드 할 파일을 골라주세요.

 

다 작성했다면 Send 버튼을 클릭해 파일 업로드를 시도합니다. 200OK와 함께 업로드에 성공한 것을 확인할 수 있습니다. 만약 HTTPS로 인해 문제가 생긴다면 Postman에서 https를 이용하지 않도록 하는 옵션이 있으니 참고해 주세요. 

 

 

이후 브라우저를 통해 정상적으로 업로드 한 파일을 확인할 수 있습니다.

 

 

 

4. 버켓 내 파일 조회하기.

 

이제 업로드를 하였으니 업로드 한 파일을 조회하는 방법에 대해 알아봅니다. 컨트롤러 클래스에 다음 코드를 추가해 주세요.

 

// 중간 생략...
using Newtonsoft.Json;
using System.Collections.Generic;
// 중간 생략...
        [HttpGet("GetFileList")]
        public async Task<ActionResult> GetFileList()
        {
            var req = HttpContext.Request;
            var form = req.Form;
            string bucketName = form["bucketname"];
            try
            {
                using (var client = new AmazonS3Client(_accessKeyId, _secretAccessKey, _s3Config))
                {
                    List<Dictionary<string, string>> listS3Objs = new List<Dictionary<string, string>>();
                    var listObjectsResponse = await client.ListObjectsAsync(bucketName);
                    foreach (var obj in listObjectsResponse.S3Objects)
                    {
                        Dictionary<string, string> dicObjInfo = new Dictionary<string, string>();
                        dicObjInfo["Bucket"] = obj.BucketName;
                        dicObjInfo["Key"] = obj.Key;
                        dicObjInfo["Size"] = Convert.ToString(obj.Size);
                        dicObjInfo["Tag"] = obj.ETag;
                        dicObjInfo["Modified"] = obj.LastModified.ToString("yyyyMMddHHmmss");
                        dicObjInfo["Owner"] = Convert.ToString(obj.Owner);
                        dicObjInfo["StorageClass"] = obj.StorageClass;
                        listS3Objs.Add(dicObjInfo);
                    }
                    string jsonResult = JsonConvert.SerializeObject(listS3Objs);
                    return Ok(jsonResult);
                }
            }
            catch (Exception e)
            {
                return StatusCode(500, e.Message);
            }
        }

 

그다지 어렵지 않습니다. 아까와 같이 S3 클라이언트를 생성하고 bucketName을 이용해 오브젝트 리스트를 가져옵니다. 가져온 정보는 Dictionary를 이용해 구조화하고 List에 넣어둡니다. 그 후 모든 파일을  JSON으로 변경해 리턴하는 게 전부입니다.

 

만약 버킷 이름이 공백이면 다음과 같은 에러 메시지를 리턴합니다.

 

BucketName is a required property and must be set before making this call. (Parameter 'ListObjectsRequest.BucketName')

 

또한 존재하지 않는 버킷 이름을 전송한다면 다음과 같은 에러 메시지를 리턴합니다.

 

The specified bucket does not exist

 

이제 테스트를 해봅시다. 다시 Postman을 열고 다음과 같이 GET 요청을 작성합니다.

 

 

요청 주소를 자신의 환경에 맞게 수정한 뒤 bucketname을 파일을 업로드한 버킷 이름으로 설정해 준 뒤 Send 버튼을 클릭합니다.

 

[{"Bucket":"test-0","Key":"uploadtest.txt","Size":"11","Tag":"\"06e0e6637d27b2622ab52022db713ce2\"","Modified":"20201023135946","Owner":"Amazon.S3.Model.Owner","StorageClass":"STANDARD"}]

 

JSON 포맷으로 결과를 잘 받아오는 걸 확인할 수 있습니다.

 

 

 

 

반응형

+ Recent posts