서버 없이 AWS S3에 이미지 업로드

AWS S3는 AWS(Amazon Web Services)가 제공하는 많은 서비스 중 하나로 파일을 저장할 수 있습니다. 대부분의 사람들이 알고 있을 것입니다.한편, AWS Lambda는 현재 가장 혁명적인 서비스 중 하나로 이름이 무섭게 들릴 수도 있지만 AWS Lambda는 코드 개발에 필요한 계산 자원을 자율적으로 관리하고 모든 유형의 응용 프로그램이나 백엔드 서비스에 코드를 실행할 수 있는 계산 플랫폼으로 이 서비스의 목적은 응용 프로그램의 창설을 간소화하는 것이다.서버를 설정하거나 관리할 필요가 없기 때문입니다. AWS Lambda는 고가용성으로 코드를 실행하고 확장하는 데 필요한 모든 것을 책임지고 있으며, 코드를 실행하는 데 필요한 처리 시간을 지불해야 하기 때문입니다.
이 글의 목적은 백엔드 서비스를 어떻게 개발하는지 설명하는 것이다. 서버serverless가 없는 상황에서 코카콜라사가 개발한 serverless라는 프레임워크로 이미지(원본 이미지와 축소판)를 업로드하여 서버 없는 응용 프로그램을 더욱 빨리 만들 수 있도록 하는 것이다.위키백과에 따르면
서버 프레임워크가 없는 것은 Node로 작성된 무료, 소스 오픈 웹 프레임워크입니다.js.Serverless는 AWS Lambda에서 응용 프로그램을 구축하는 데 사용되는 첫 번째 프레임워크입니다. AWS Lambda는 Amazon이 Amazon 웹 서비스의 일부로 제공하는 서버 없는 계산 플랫폼입니다.
다음 몇 가지 단계에서 AWS S3에서 이미지 처리와 업로드를 할 수 있는 서비스 없는 응용 프로그램을 구축하도록 안내합니다. 코드here에 직접 들어가고 싶으면.
주의: Api GatewayLambdas의 일부 제한으로 인해 Lambdas를 사용하여 파일을 업로드하는 것을 권장하지 않습니다. 그럼에도 불구하고 그것을 원한다면 이 블로그는 당신을 위해 준비한 것입니다.
필요한 도구
  • 노드 JS 12
  • 서버 없음
  • AWS CLI
  • 1. AWS CLI 설치(명령줄 인터페이스)


    AWS CLI는 여러 AWS 서비스를 명령줄에서 제어할 수 있는 AWS 서비스를 관리하는 통합 도구입니다.다운로드 후 해당 AWS account and credential 에 개인 정보를 추가합니다.

    2. 서버 프레임워크 없음 설치


    여기에 이 과정을 상세하게 설명하는 링크가 있다https://serverless.com/framework/docs/getting-started/.

    3. 다음 명령을 실행하여 서버less를 사용하여 예시 코드를 생성합니다.


    우선, 예를 들어 Servless upload image와 같은 폴더를 만들어야 합니다.
    sls create --template hello-world
    
    위의 명령은 다음 파일을 생성합니다.
  • 서버가 없습니다.yml
  • 프로세서.js
  • 서버가 없습니다.yml 파일에서 코드 개발에 필요한 자원에 대한 모든 정보를 찾을 수 있습니다. 예를 들어 AWS, 구글 클라우드나 Azure, 사용할 데이터베이스, 표시할 기능, 들을 이벤트, 모든 자원에 접근할 권한 등입니다.
    손잡이.js 파일에는 생성된 Hello 월드 코드가 포함되어 있습니다. 이것은 간단한 함수입니다. 상태가 200인 JSON 문서와 메시지를 되돌려줍니다.이 파일의 이름을 fileUploaderHome으로 변경합니다.js.

    4. 종속성 설치


    npm init -y
    npm install busboy && uuid && jimp && aws-sdk
    
    파일을 처리해야 하기 때문에 클라이언트는 POST 요청을 보내고 여러 부분/폼 데이터 형식으로 본문을 인코딩하여 이 형식을 디코딩합니다. 저희는 busboy 라이브러리를 사용할 것입니다.그 밖에 이미지의 축소판을 만들 필요가 있다. Jimp, uid라고도 불리는 라이브러리를 설치하여 이미지를 만드는 유일한 표지부호를 만들 것이다. 마지막으로 AWS SDK는 자바스크립트 대상을 제공하여 AWS 서비스를 관리한다. 예를 들어 Amazon S3, Amazon EC2, DynamoDB 등이다.

    5. 다중 부분 / 폼 데이터 디코딩 함수 만들기


    //formParser.js
    const Busboy = require('busboy');
    
    module.exports.parser = (event, fileZise) =>
        new Promise((resolve, reject) => {
        const busboy = new Busboy({
            headers: {
                'content-type':
                event.headers['content-type'] || event.headers['Content-Type']
            },
            limits: {
                fileZise
            }
        });
    
        const result = {
            files: []
        };
    
        busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
            const uploadFile = {}
            file.on('data', data => {
                uploadFile.content = data
            });
            file.on('end', () => {
                if (uploadFile.content) {
                    uploadFile.filename = filename
                    uploadFile.contentType = mimetype
                    uploadFile.encoding = encoding
                    uploadFile.fieldname = fieldname
                    result.files.push(uploadFile)
                 }
            })
        })
    
        busboy.on('field', (fieldname, value) => {
            result[fieldname] = value
        });
    
        busboy.on('error', error => {
            reject(error)
        })
    
        busboy.on('finish', () => {
            resolve(result);
        })
    
        busboy.write(event.body, event.isBase64Encoded ? 'base64' : 'binary')
        busboy.end()
     })
    

    6, 이미지를 처리하고 S3에 업로드하는 기능


    다음은 원본 이미지와 축소판을 S3에 업로드할 수 있는 코드입니다.
    //fileUploaderHome.js
    "use strict";
    const AWS = require("aws-sdk")
    const uuid = require("uuid/v4")
    const Jimp = require("jimp")
    const s3 = new AWS.S3()
    const formParser = require("./formParser")
    
    const bucket = process.env.Bucket
    const MAX_SIZE = 4000000 // 4MB
    const PNG_MIME_TYPE = "image/png"
    const JPEG_MIME_TYPE = "image/jpeg"
    const JPG_MIME_TYPE = "image/jpg"
    const MIME_TYPES = [PNG_MIME_TYPE, JPEG_MIME_TYPE, JPG_MIME_TYPE]
    
    module.exports.handler = async event => {
        try {
            const formData = await formParser.parser(event, MAX_SIZE)
            const file = formData.files[0]
    
            if (!isAllowedFile(file.content.byteLength, file.contentType))
                getErrorMessage("File size or type not allowed")
    
            const uid = uuid()
            const originalKey = `${uid}_original_${file.filename}`
            const thumbnailKey = `${uid}_thumbnail_${file.filename}`
    
            const fileResizedBuffer = await resize( file.content, file.contentType, 460)
            const [originalFile, thumbnailFile] = await Promise.all([
                uploadToS3(bucket, originalKey, file.content, file.contentType),
                uploadToS3(bucket, thumbnailKey, fileResizedBuffer, file.contentType)
            ])
    
            const signedOriginalUrl = s3.getSignedUrl("getObject", { Bucket: originalFile.Bucket, Key: originalKey, Expires: 60000 })
            const signedThumbnailUrl = s3.getSignedUrl("getObject", { Bucket: thumbnailFile.Bucket, Key: thumbnailKey, Expires: 60000 })
    
            return {
                statusCode: 200,
                body: JSON.stringify({
                    id: uid,
                    mimeType: file.contentType,
                    originalKey: originalFile.key,
                    thumbnailKey: thumbnailFile.key,
                    bucket: originalFile.Bucket,
                    fileName: file.filename,
                    originalUrl: signedOriginalUrl,
                    thumbnailUrl: signedThumbnailUrl,
                    originalSize: file.content.byteLength
                 })
              }
        } catch (e) {
            return getErrorMessage(e.message)
        }
    }
    
  • 잠시 후 크기 조정 기능(file.content, file.content Type, 460)을 상세하게 설명하지만, 이 줄에서 원본 이미지에서 축소판 그림을 생성합니다. 폭은 460px이고 높이는 자동으로 결정됩니다. 이 기능은 원본 파일의 바이너리 내용, 파일의 유형과 축소판 그림의 크기를 수신합니다.wait 키워드는 다음 줄을 계속하기 위해 이미지 크기 조정이 완료될 때까지 기다립니다.
  • uploadToS3 함수는 업로드된 버킷, 파일의 키 (key), 바이너리 내용과 파일 형식 등 3개의 인자를 수신하고 약속을 되돌려줍니다. 잠시 후 이 함수의 작용을 상세하게 설명합니다.
  • 원본 파일과 미리 보기 그림 파일이 있으면 Promise와 함께 S3에 업로드됩니다.모두(...),모든 파일을 업로드한 후, 업로드된 모든 파일의 정보를 포함하는 수조로 되돌아옵니다.그리고 AWS S3 클라이언트를 사용하여 지정된 만료 시간이 있는 서명 URL*(getSignedUrl)**를 받습니다.
    마지막으로 모든 작업이 성공적으로 수행되면 처리된 이미지에 대한 정보가 포함된 JSON이 반환됩니다.
  • 아래의 코드 블록에서 이전 코드 블록에 사용된 모든 실용적인 기능을 상세하게 소개하였다.
    const getErrorMessage = message => ({ statusCode: 500, body: JSON.stringify( message })})
    
    const isAllowedFile = (size, mimeType) => { // some validation code }
    
    const uploadToS3 = (bucket, key, buffer, mimeType) =>
        new Promise((resolve, reject) => {
            s3.upload(
                { Bucket: bucket, Key: key, Body: buffer, ContentType: mimeType },
                function(err, data) {
                    if (err) reject(err);
                    resolve(data)
                })
        })
    
    const resize = (buffer, mimeType, width) =>
        new Promise((resolve, reject) => {
            Jimp.read(buffer)
            .then(image => image.resize(width, Jimp.AUTO).quality(70).getBufferAsync(mimeType))
            .then(resizedBuffer => resolve(resizedBuffer))
            .catch(error => reject(error))
        })
    
    지금까지 우리는 이미지 처리, 검증, S3에 업로드할 수 있는 모든 코드 블록을 되돌아보았지만, 제어 파일에는 서버가 없습니다.서버 프레임워크가 없는yml을 소개해야 합니다. 서비스의 자원, 서비스 정의, 역할, 설정, 권한 등을 상세하게 소개할 수 있습니다.
    #serverles.yml
    service: file-UploaderService-foqc-home
    custom:
        bucket: lambda-test-foqc-file-home
    provider:
        name: aws
        runtime: nodejs12.x
        region: us-east-1
        stackName: fileUploaderHome
        apiGateway:
            binaryMediaTypes:
                - '*/*'
        iamRoleStatements:
            - Effect: "Allow"
            Action:
                - "s3:PutObject"
                - "s3:GetObject"
            Resource:
                - "arn:aws:s3:::${self:custom.bucket}/*"
    functions:
        UploadFileHome:
            handler: fileUploaderHome.handler
            events:
                - http:
                    path: upload
                    method: post
                    cors: true
            environment: Bucket: ${self:custom.bucket}
    resources:
        Resources:
            StorageBucket:
                Type: "AWS::S3::Bucket"
                Properties:
                    BucketName: ${self:custom.bucket}
    
  • 서비스는 하나의 프로젝트를 가리키며 배치될 이름이다.
  • 사용자 정의, 이 절에서 문서의 다른 점에서 사용할 수 있는 변수, 집중 값을 정의할 수 있습니다​​따라서 개발이나 배치를 위해 버킷 변수를 추가했습니다. 값은 lambdatestfoqcfile home입니다. 이 값은 파일을 저장하는 버킷을 정의하는 데 사용됩니다.
  • 공급자는 본 절에서 공급자, 인프라 시설과 자원에 대한 상응하는 권한을 정의했다.이 블로그의 첫머리에서 말한 바와 같이 사용할 공급자는 Amazon Web Services (aws), NodeJs 12입니다. 이것은 미국 동부에 배치됩니다. 이것은 CloudFormation 창고 (file Uploader Home) 의 기본 이름이지만 필요하지 않습니다.
    다음 몇 줄은 매우 중요합니다. 우리의Api 게이트웨이가 바이너리 파일을 지원할 수 있도록 합니다.apiGateway 부분을 설명해야 합니다. 이 부분의 값 중 하나는​​'*/*', 이것은 다중 부분/폼 데이터와 같은 이진 형식을 정의하는 어댑터입니다.그리고 사용자 정의 부분 ${self.custom.bucket}에 정의된 S3 bucket에 접근할 수 있도록 권한을 정의합니다.
  • 기능, 본 절은 기능의 모든 실현을 서비스(Faas)로 정의한다. 이것은 최소한의 배치 단원으로 하나의 서비스는 여러 가지 기능으로 구성할 수 있고 모든 기능은 하나의 임무를 완성해야 한다. 비록 이것은 하나의 건의일 뿐이지만.모든 함수는 특정한 설정이 있어야 한다. 그렇지 않으면 기본적으로 그것을 계승할 것이다.
    우리의 함수 이름은 UploadFileHome입니다. 이것은 HTTP POST 이벤트에서 호출된 것입니다. 이 이벤트는 필요에 따라 시작하고 CORS를 허용하는 경로에 있습니다. 이 이벤트는 우리의 프로세서 함수에 의해 처리됩니다. 이 함수는 파일 *fileUploaderHome에서 실행되었습니다.
  • 자원, 마지막으로 이 절에서 상술한 각 기능에 사용할 자원을 정의했다.스토리지 버킷(StorageBucket)을 정의합니다. 유형은 (AWS::S3:bucket), 속성은 스토리지 버킷의 이름(BucketName)입니다.
  • 마지막우리는 이미 서비스의 구축을 완성했다. 이 서비스는 이미지와 축소판을 S3에 업로드하기 때문에 이제 다음 명령을 사용하여 이 서비스를 배치할 때가 되었다.
    sls deploy --stage=test
    
    배치가 끝날 때, 우리 서비스의 URL을 표시하고postman을 사용하여 동작을 테스트합니다. 그림과 같습니다.

    이미지가 업로드되면 서비스는 처리된 이미지의 정보, 예를 들어 키, 이름, 원본 파일의 URL, 축소 이미지 등을 포함하는 JSON을 되돌려줍니다.
    한 마디로 하면 서비스를 삭제해야 한다면 다음 명령을 실행하십시오.
    sls remove --stage=test
    

    결론


    이 서비스는 모든 외부 응용 프로그램이나 서비스가 필요에 따라 사용할 수 있습니다. 업무 논리에 결합되지 않기 때문입니다. 또한 코드를 재구성하여 일반 파일을 업로드할 수 있습니다. 이미지뿐만 아니라 httppost 이벤트의 일부분으로 저장된 파일을 수신하는 저장통의 디렉터리(경로)로 고정된 디렉터리를 사용하지 않도록 합니다.그러나 설교의 방식으로, 그것은 더욱 건장하고 설정 가능한 서비스를 만드는 기초이다.
    나는 며칠 동안 이 글을 기록하고 쓰는 데 시간을 썼다. 나는 매우 만족한다. 나는 이 정보들이 너에게 유용하길 바란다.
    정말 감사합니다.

    좋은 웹페이지 즐겨찾기