Saturday, May 11, 2019

AWS Lambda와 API Gateway 활용, S3에 Multipart 이미지 업로드 시 파일 깨짐 문제 해결

AWS API Gateway와 Lambda
AWS API Gateway와 Lambda

서비스 개발 중에 클라이언트에서 multipart로 사진을 AWS Lambda로 보내고, Lambda에서 S3로 다시 사진을 업로드하는 작업이 필요했습니다. Flutter를 이용해 서비스를 개발하려 했으나 아직 Flutter용(dart) SDK가 없어서 우리쪽 서버를 거쳐서 보내기로 결정했습니다.

미디어 타입 설정

Lambda 코드 작성 전에 API gateway에서 미디어 타입을 추가해야 합니다.

API Gateway 미디어 타입 설정
API Gateway에서 미디어 타입 설정하기

코드 작성 및 팁 공유

인터넷에서 여러 자료를 참고하여 아래와 같은 코드를 작성했습니다. 이 예제는 여러 장의 사진을 받아 1장만 S3로 업로드하는 방법입니다. 한 가지 팁으로는, AWS SDK가 이미 설치되어 있으므로 별도의 설치가 필요하지 않다는 점입니다.


//const AWS = require('aws-sdk');
const multipart = require('parse-multipart');
exports.handler = (event, context, callback) => {
    const s3 = new AWS.S3({
        credentials: {
            accessKeyId: 'your accessKeyId',
            secretAccessKey: 'your secretAccessKey',
        },
        params: { Bucket: 'your Bucket' }
    });

    let bodyBuffer = Buffer.from(event['body-json'], 'base64');
    let boundary = multipart.getBoundary(event.params.header['content-type']);
    let parts = multipart.Parse(bodyBuffer, boundary);
    let data = {
        Key: 'your path',
        Body: parts[0].data,
        ContentEncoding: 'base64',
        ContentType: 'image/jpeg'
    };

    s3.putObject(data, function (err, data) {
      if (err) {
          callback(null, err);
      } else {
          callback(null, data);
      }
   });
};

테스트 및 문제 해결


<html>
<body>
<form action="https://your-url" enctype="multipart/form-data" method="post">
    <input multiple="" name="body-json" type="file" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

위와 같이 웹페이지를 만들어 테스트를 진행했지만 어떤 때는 동작하고 어떤 때는 동작하지 않는 이상한 상황이 발생했습니다. 원인을 찾기 위해 여러 가지 시도를 해봤지만 결국 문제의 원인은 웹에서 보낼 때 캐릭터셋 지정이 없어서 한글 파일의 경우 파일명이 깨지고 전송 후에 파일 자체가 깨지는 것이었습니다. 이를 해결하기위해 form 태그 안에 accept-charset="UTF-8"속성을 추가하고 다시 테스트해 보니 문제가 해결되었고, S3 업로드도 잘 실행되었습니다.


<html>
<body>
<form action="https://your-url" enctype="multipart/form-data" method="post" accept-charset="UTF-8">
    <input multiple="" name="body-json" type="file" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

사실상 코드는 큰 문제가 없었는데 캐릭터셋을 생각하지 못하고 코드 문제인 줄 알아서 이것저것 시도하느라 시간을 많이 잡아먹었습니다. 혹시 같은 작업이나 비슷한 문제를 겪는 사람들에게 조금이라도 도움이 되길 바랍니다.

참고 : 여러 형식의 파일 multipart upload 방법(https://blogdeveloperspot.blogspot.com/2019/12/aws-apigateway-lambdanodejs-multipart.html)


0 개의 댓글:

Post a Comment