반응형
< (3) SNS 서비스 개발
(사진 포스팅 + 태그 자동 번역 기능) >
# 사진 포스팅 기능 : 사진 1장 + 내용을 포스팅
- 사진 포스팅에 대한 CRUD 기능 있어야함!
- 생성된 태그는 자동 번역되어 출력되도록 설계
- 우선 사진 저장을 위해서 AWS S3에서 새로운 버킷 생성
# 화면 구성을보고 필요한 DB 설계
- 포스팅을 가져오는 API는 내친구들의 포스팅만!
- 다음처럼 Response가 오도록 설계 => postID, imgUrl, content, userId, email (DB 컬럼명은 헝가리안 표기법으로 사용하는게 작업에 용이함)
- 태그를 받아오기위한 DB도 필요!
# DB 생성까지 완료되었고, Postman을 실행시켜 API 리퀘스트 생성
- Headers도 Authorization로 토큰 사용할수 있도록 설정해 준다.
# Visual Studio Code에서 코드 작성!
- resources 폴더안에 posting.py라는 파일로 생성하여 작성
- AWS의 번역 API도 사용함 태그해석을 위해
from flask import request
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_restful import Resource
from mysql_connection import get_connection
from mysql.connector import Error
from datetime import datetime
import boto3
from config import Config
class PostingListResource(Resource) :
# 포스팅하는 API
@jwt_required()
def post(self) :
#1. 클라이언트로부터 데이터 받아온다.
if 'image' not in request.files :
return {'result' : 'fail' ,
'error' : '파일을 업로드 하세요.'}, 400
if 'content' not in request.form :
return {'result' : 'fail' ,
'error' : '내용을 작성하세요.'}, 400
file = request.files['image']
content = request.form['content']
user_id = get_jwt_identity()
#2. 사진을 S3에 업로드 한다.
if file is None :
return {'result' : 'fail' ,
'error' : '파일을 업로드 하세요.'}, 400
if 'image' not in file.content_type :
return {'result' : 'fail',
'error' : '이미지 파일만 업로드 가능합니다.'}, 400
client = boto3.client('s3',
aws_access_key_id = Config.AWS_ACCESS_KEY,
aws_secret_access_key = Config.AWS_SECRET_ACCESS_KEY)
# 파일 이름을 유니크하게 만들어줘야 한다.
current_time = datetime.now()
file_name = current_time.isoformat().replace(':','_') + str(user_id) + '.jpg'
file.filename = file_name
# 버킷을 만들어야 한다.
try :
client.upload_fileobj(file,
Config.AWS_S3_BUCKET,
file.filename,
ExtraArgs = {'ACL' : 'public-read',
'ContentType' : 'image/jpeg'})
except Exception as e:
return {'result' : 'fail',
'error' : str(e)}, 500
#3. 업로드한 사진의 URL을 만든다.
image_url = Config.AWS_FILE_URL + file.filename
#3-2. rekognition 을 이용해서, object detection 하여,
# 태그로 사용할 label 을 뽑는다.
label_list = self.detect_labels(file.filename, Config.AWS_S3_BUCKET)
label_str = ','.join(label_list)
label_str = self.translate(label_str)
label_list = label_str.split(', ')
#4. DB에 userID, imageUrl, content를 저장한다.
try :
connection = get_connection()
query = '''insert into posting
(userId, imageUrl, content)
values
(%s, %s, %s);'''
record = (user_id, image_url, content)
cursor = connection.cursor()
cursor.execute(query, record)
posting_id = cursor.lastrowid
for label in label_list:
# tag 테이블에, label이 있는지 확인해서,
# 있으면 아이디를 가져오고, 없으면 인서트한 후에 아이디를 가져온다.
query = '''select *
from tag
where name = %s;'''
record = (label, )
cursor = connection.cursor(dictionary=True)
cursor.execute(query, record)
result_list = cursor.fetchall()
# 혹은 != 0 / 0이 아니면
if len(result_list) == 1 :
tag_id = result_list[0]['id']
else :
query = '''insert into tag
(name)
values
(%s);'''
record = (label, )
cursor = connection.cursor()
cursor.execute(query, record)
tag_id = cursor.lastrowid
# 위에 tagId를 posting_tag 테이블에, postingID 와 함께 넣어준다.
query = '''insert into posting_tag
(postingId, tagId)
values
(%s, %s);'''
record = (posting_id, tag_id)
cursor = connection.cursor()
cursor.execute(query, record)
connection.commit()
cursor.close()
connection.close()
except Error as e :
if cursor is not None:
cursor.close()
if connection is not None:
connection.close()
return {'result' : 'fail',
'errer' : str(e)}, 500
#5. 클라이언트에 json으로 응답한다.
return {'result' : '업로드가 완료되었습니다.',
'url' : Config.AWS_FILE_URL + file_name}
# AWS 레코그니션 사용을 위한 함수
def detect_labels(self, photo, bucket):
client = boto3.client('rekognition',
'ap-northeast-2',
aws_access_key_id = Config.AWS_ACCESS_KEY,
aws_secret_access_key = Config.AWS_SECRET_ACCESS_KEY)
response = client.detect_labels(Image={'S3Object':{'Bucket':bucket,'Name':photo}},
MaxLabels=10,
# Uncomment to use image properties and filtration settings
#Features=["GENERAL_LABELS", "IMAGE_PROPERTIES"],
#Settings={"GeneralLabels": {"LabelInclusionFilters":["Cat"]},
# "ImageProperties": {"MaxDominantColors":10}}
)
print('Detected labels for ' + photo)
print()
print(response['Labels'])
label_list = []
for label in response['Labels']:
print("Label: " + label['Name'])
label_list.append(label['Name'])
return label_list
# 번역 API 사용을 위한 함수
def translate(self, text) :
client = boto3.client(service_name='translate',
region_name='ap-northeast-2',
aws_access_key_id = Config.AWS_TRANSLATE_ACCESS_KEY,
aws_secret_access_key = Config.AWS_TRANSLATE_SECRET_ACCESS_KEY)
result = client.translate_text(Text=text,
SourceLanguageCode="en",
TargetLanguageCode="ko")
print('TranslatedText: ' + result.get('TranslatedText'))
print('SourceLanguageCode: ' + result.get('SourceLanguageCode'))
print('TargetLanguageCode: ' + result.get('TargetLanguageCode'))
return result.get('TranslatedText')
# app.py에도 연결 코드 작성
import serverless_wsgi
from flask import Flask
from flask_restful import Api
from flask_jwt_extended import JWTManager
from config import Config
from resources.follow import FollowResource
from resources.like import LikeResource
from resources.posting import PostingListResource
from resources.user import UserLoginResource, UserLogoutResource, UserRegisterResource, jwt_blacklist
app = Flask(__name__)
# 환경변수 셋팅
app.config.from_object(Config)
# JWT 매니저 초기화
jwt = JWTManager(app)
# 로그아웃된 토큰으로 요청하는 경우, 처리하는 함수 작성
@jwt.token_in_blocklist_loader
def check_if_token_is_revoked(jwt_header, jwt_payload) :
jti = jwt_payload['jti']
return jti in jwt_blacklist
api = Api(app)
# 경로와 리소스를 연결하는 코드 작성
api.add_resource( UserRegisterResource , '/user/register')
api.add_resource( UserLoginResource , '/user/login')
api.add_resource( UserLogoutResource , '/user/logout')
api.add_resource( PostingListResource , '/posting')
def handler(event, context) :
return serverless_wsgi.handle_request(app, event, context)
if __name__ == '__main__':
app.run()
# Postman 에서 send보내고 링크로 이미지 확인 및 VSC에서 자동 번역 문구 출력도 확인
다음 게시글로 계속~!
728x90
반응형
'API 개발 > API 개발 Project' 카테고리의 다른 글
API Project : (2) SNS 서비스 개발 (회원가입, 로그인, 로그아웃 기능) (0) | 2024.05.30 |
---|---|
API Project : (1) SNS 서비스 개발 (기본 세팅부터 진행!) (0) | 2024.05.29 |
API Project : (2) 영화 추천 API 개발 (대용량 파일 Docker 서버 배포) (1) | 2024.05.29 |
API Project : (1) 영화 추천 API 개발 (DB 데이터 json으로 가져오기) (0) | 2024.05.29 |
API Project : 메모앱 API 서버 개발 (0) | 2024.05.29 |