AWS

AWS API를 이용한 lambda S3 mysql flask boto3 postman 업로드한 사진 오브젝트 디텍팅

leopard4 2023. 1. 13. 11:30

사전배경지식은 생략하였음.

 

photo밑이 가려서 ..

 

이런 API를 S3에 업로드하고 DB에 저장할것임

 

유저가 이미지와 텍스트를 request 했을때 S3에 url을 저장하고 DB에 저장하는 VSC

from flask import request # 클라이언트가 보낸 데이터를 받기 위한 라이브러리
from flask_restful import Resource # API를 만들기 위한 라이브러리
from mysql.connector import Error # DB에 연결할 때, 에러가 발생할 수 있으므로, 에러처리를 위한 라이브러리
from flask_jwt_extended import jwt_required, get_jwt_identity # JWT를 사용하기 위한 라이브러리
from mysql_connection import get_connection
from config import Config
from datetime import datetime # 현재 시간을 가져오기 위한 라이브러리
import boto3


class PostingResource(Resource):
   
    def post(self):
        # 1.클라이언트가 보낸 데이터를 받는다.
        # form-data
        # photo : file
        # content : text

        # 사진과 내용은 필수항목이다!! (세이프코드)
        if 'photo' not in request.files or 'content' not in request.form :
            return {'error': '데이터를 정확히 보내세요'}, 400
       
        file = request.files['photo']
        content = request.form['content']
       
        # 사진인지 아닌지 확인
        if file.content_type.split('/')[0] != 'image' :
            return {'error' : '이미지 파일만 업로드 가능합니다.'}, 400

       
        # 파일명을 어떻게 할 것인가?
        # 현재 시간을 가져온다. 합친다.
        current_time = datetime.now()
       
     
        # 파일이 이미지인지 pdf인지 확인하여 확장자를 붙여준다.
        new_file_name = current_time.isoformat().replace(':', '').replace('_', '')+ '.' + file.content_type.split('/')[1]

        print(new_file_name)
        print("콘텐츠 타입은:", file.content_type)

        file.filename = new_file_name

      
        # tip.순서는 러프(대충)하게 작성하고, 세세한 부분은 나중에 작성한다.
        # 2. 사진을 먼저 S3에 업로드한다.
        # 2-1. S3에 접속한다.
        client = boto3.client('s3',
            aws_access_key_id=Config.ACCESS_KEY,
            aws_secret_access_key=Config.SECRET_ACCESS
        )

        # 2-2. S3에 파일을 업로드한다.
       

        try :
            client.upload_fileobj( file , # 파일을 업로드한다.
                        Config.BUCKET_NAME ,
                        new_file_name,
                        ExtraArgs={'ACL':'public-read',
                        'ContentType' : file.content_type})  # ExtraArgs={'ACL':'public-read'} : 파일을 업로드할 때, 권한을 설정한다.
                   
        except Error as e :
            return {'error' : str(e)}, 500
       

        # 3. 저장된 사진의 imgUrl을 만든다.
        imgUrl = Config.S3_LOCATION + new_file_name
       
        # 4. DB에 저장한다
        try :
            connection = get_connection()
            query = '''insert into posting
                        (content, imageUrl)
                        values
                        (%s, %s);'''
            record = (content, imgUrl)
            cursor = connection.cursor()
            cursor.execute(query,record)
            connection.commit()
            cursor.close()
            connection.close()
           
        except Error as e :
            print(e)
            cursor.close()
            connection.close()
            return {'error' : str(e)}, 500

        return {'result' : 'success'}, 200

       

 

테이블설계

 

 

 

 

오브젝트 디텍팅 ( aws의 ai 객체인식 api를 이용할것)

 

postman

 

vsc

from flask import request
from flask_restful import Resource
from mysql.connector import Error
from config import Config
import boto3
from datetime import datetime

class ObjectDetectionResource(Resource) :

    # S3에 저장된 이미지를 분석하여 객체를 탐지하는 API
    def get(self) :
       
        # 1. 클라이언트로부터 파일명을 받아온다.
        filename = request.args.get('filename')

        # 2. 위의 파일은 이미 S3에 저장되어 있다고 가정한다.
        # 따라서 aws의 rekognition 서비스를 이용하여
        # object detection을 수행한다.

        # rekognition 서비스를 사용하기 위해서는
        # iam 의 유저 권한을 확인하고, 설정해준다.
        client = boto3.client( 'rekognition',
                            'ap-northeast-2',
                            aws_access_key_id=Config.ACCESS_KEY,
                            aws_secret_access_key=Config.SECRET_ACCESS )

        response = client.detect_labels( Image = { 'S3Object' : { 'Bucket' : Config.BUCKET_NAME, 'Name' : filename } } ,
                            MaxLabels = 10 )
       
        print("response:  ", response)

        for label in response['Labels']:
            print ("Label: " + label['Name'])
            print ("Confidence: " + str(label['Confidence']))
            print ("Instances:")
            for instance in label['Instances']:
                print ("  Bounding box")
                print ("    Top: " + str(instance['BoundingBox']['Top']))
                print ("    Left: " + str(instance['BoundingBox']['Left']))
                print ("    Width: " +  str(instance['BoundingBox']['Width']))
                print ("    Height: " +  str(instance['BoundingBox']['Height']))
                print ("  Confidence: " + str(instance['Confidence']))
                print()

            print ("Parents:")
            for parent in label['Parents']:
                print ("   " + parent['Name'])
            print ("----------")
            print ()

        return {'result' : 'success',
                'Labels' : response['Labels'][0]["Name"] }, 200

class PhotoRekognitionResource(Resource) :
   
    def post(self):
       
        # 1. 클라이언트가 보낸 데이터를 받는다.
        # request.files : 클라이언트가 보낸 파일 데이터
        if 'photo' not in request.files :
            return {'message' : 'No file'}, 400

        file = request.files['photo']
     
        # 클라이언트가 보낸 파일의 파일명을
        # 변경시켜서 S3에 올려야, 유니크하게
        # 파일을 관리할 수 있다.
       
        # 파일명을 유니크하게 만드는 방법
        current_time = datetime.now()
        new_file_name = current_time.isoformat().replace(':', '').replace('_', '')+".jpg"

        print(new_file_name)

        # 파일명을, 유니크한 이름으로 변경한다.
        # 클라이언트가 보낸 파일명을 변경한다.
       
        file.filename = new_file_name

        # s3에 파일을 업로드한다.
        # s3에 파일 업로드 하는 라이브러리가 필요하다.
        # 따라서, pip install boto3 라이브러리를 이용해서
        # 업로드한다.

        # AWS S3에 접속한다.
        client = boto3.client( 's3' ,
            aws_access_key_id= Config.ACCESS_KEY ,
            aws_secret_access_key= Config.SECRET_ACCESS )
       
        try :
            client.upload_fileobj( file , # 파일을 업로드한다.
                        Config.BUCKET_NAME ,
                        new_file_name,
                        ExtraArgs={'ACL':'public-read',
                        'ContentType' : file.content_type})  # ExtraArgs={'ACL':'public-read'} : 파일을 업로드할 때, 권한을 설정한다.
                   
        except Error as e :
            return {'error' : str(e)}, 500


        client = boto3.client( 'rekognition',
                            'ap-northeast-2',
                            aws_access_key_id=Config.ACCESS_KEY,
                            aws_secret_access_key=Config.SECRET_ACCESS )

        response = client.detect_labels( Image = { 'S3Object' : { 'Bucket' : Config.BUCKET_NAME, 'Name' : new_file_name } } ,
                            MaxLabels = 10 )
       
        print( response["Labels"])


        #### 위의 response 에서, 필요한 데이터만 가져와서
        #### 클라이언트에게 보내준다!

        # response 구조를파악하고 labels : [ 'Person', 'Human', 'cat' ] 와 같은 형태로 만듬
        # json online editor 를 이용

        name_list = []
        for data in response["Labels"]:
            name_list.append(data["Name"])
       
        return {'result' : 'success', 'Labels' : name_list}, 200


S3 버킷