본문 바로가기
Restful API

[Restful API] 이미지와 텍스트 포스팅하면 태그 가져오는 API만들기

by coding_su 2023. 1. 16.

📝이미지와 텍스트 포스팅하면 태그 가져오는 API만들기

순서

1. 클라이언트가 보낸 데이터 받아오기

2. 사진을 S3에 저장한다

- AWS콘솔로 가서 IAM 유저 만들고 S3로 가서 이 프로젝트의 버킷을 만들고 config.py에 입력해준다

- 날짜와 유저 아이디를 이용해 파일명을 유니크하게 만든다

- S3에 파일 업로드 한다(boto3 라이브러리 사용한다 설치 안되어있으면 pip install boto3로 설치)

3. S3에 저장된 사진을 Object Detectin(AWS Rekognition 이용)

 - for루프로 Labels 안에 있는 Name만 가져온다

4. 위에서 가져온 imgURL과 태그로 저장할 Labels 이름을 DB에 저장한다(tag_name 과 tag 테이블에 인서트)

- tag_list가 tag_name 테이블에 있는지 확인해서 있으면 그 tag_name의 아이디를 가져오고 없으면 tag_name에 넣어준다

- tag테이블에 posting_id와 tag_id를 입력해 저장해준다

5. 결과를 클라이언트에 보내준다

 

※ 테이블 설계는 아래 사진처럼 했다

class PostingResource(Resource) :
    # 포스팅 작성 API
    @jwt_required()
    def post(slef) :

        userId = get_jwt_identity()
        
        # from=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 'image' not in file.content_type :
            return {'error' : '이미지 파일이 아닙니다.'}

        # 사진명을 유니크하게 변경해서 S3에 업로드
        # aws 콘솔로 가서 IAM 유저만들고 S3 버킷을 만들어서 config.py에 입력

        # 파일명 유니크하게 변경
        current_time = datetime.now()
        new_file_name = str(userId) + current_time.isoformat().replace(':', '_') + '.' + file.content_type.split('/')[-1]
        file.filename = new_file_name

        # 파일 S3에 업로드 (boto3사용)
        client =  boto3.client('s3', aws_access_key_id= Config.ACCESS_KEY, aws_secret_access_key= Config.SECRET_ACCESS)
        try :
            client.upload_fileobj(file, Config.S3_BUCKET, new_file_name, ExtraArgs= {'ACL' : 'public-read', 'ContentType' : file.content_type})
        
        except Exception as e :
            return {"error" : str(e)}, 500

        # 저장된 사진의 imgUrl
        imgUrl = Config.S3_LOCATION + new_file_name

        # S3저장된 사진을 Amazon Rekognition 사용하여 Object Detection
        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.S3_BUCKET, 'Name' : new_file_name}}, MaxLabels= 5)

        # 태그 저장 
        tag_list = []
        for row in response['Labels'] :
            tag_list.append(row['Name'])

        # DB에 저장
        try :
            connection = get_connection()

            # 포스팅 테이블 저장
            query = '''insert into posting
                    (userId, imgUrl, content)
                    values (%s, %s, %s);'''

            record = (userId, imgUrl, content)

            cursor = connection.cursor()

            cursor.execute(query, record)

            # 저장한 포스팅 테이블 id 가져오기
            postingId = cursor.lastrowid

            # 태그네임 테이블 저장
            # tag_list가 tag_name 테이블에 들어있는지 확인해서 있으면
            # 그 tag_name의 아이디를 가져오고 없으면 tag_name에 넣어준다
            for name in tag_list :
                query = '''select *
                        from tag_name
                        where name = %s ;'''
                record = (name, )
                cursor = connection.cursor(dictionary= True)
                cursor.execute(query, record)
                result_list = cursor.fetchall()

                if len(result_list) == 0 :
                    query = '''insert into tag_name
                    (name)
                    values (%s);'''
                    record = (name, )
                    cursor = connection.cursor()
                    cursor.execute(query, record)
                    tagId = cursor.lastrowid

                else :
                    tagId = result_list[0]['id']

                # tag 테이블에 postingId와 tagId를 저장한다
                query = '''insert into tag
                        (postingId, tagId)
                        values
                        (%s, %s)'''

                record = (postingId, tagId)

                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

 

댓글