[ 작업 환경 ]
Flask 1.1
Centos 7
1. route 파일 사전 작업
# vim app/route.py
# ...
# 이미지 업로드
import os
from datetime import datetime
from werkzeug.utils import secure_filename
UPLOAD_FOLDER_LOCATION = '/flask_api/app001/static/image'
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app.config['UPLOAD_FOLDER_LOCATION'] = UPLOAD_FOLDER_LOCATION
# allowed_file 함수 > 허용된 형태의 파일 형식인지 확인
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
allowed_file 함수는 파일 형식 허용 LIST에 업로드하려는 파일이 해당되는지 확인하기 위한 용도로 만들어두었습니다.
본 예시에서는 png, jpg, jpeg, gif 파일 업로드만을 허용합니다.
2. route 파일 upload API 개발 소스
# 이미지 업로드
@app.route('/upload/images/<location>/<id>', methods=['PUT'])
def upload_images(location, id):
if request.method == 'PUT':
# check if the post request has the file part
if 'file' not in request.files:
log = 'No File Part'
return jsonify(result=False, log=log), 404
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
log = 'No Selected File'
elif file and allowed_file(file.filename):
filename = secure_filename(file.filename)
save_location = app.config['UPLOAD_FOLDER_LOCATION'] + '/' + location + '/' + id
# 파일 저장할 디렉토리 생성 (없는 경우)
os.system('mkdir -p ' + save_location)
# filename 이름변경하기
filename_rsplit = filename.rsplit('.', 1)
new_filename = filename_rsplit[0] + '_' + datetime.now().strftime('%Y%m%d%H%M%S%f') + '.' + filename_rsplit[1]
# file 저장하기
meta_update_try = System.img_meta_update(location, id, new_filename)
if meta_update_try:
file.save(os.path.join(save_location, new_filename))
return jsonify(result=True)
log = 'Not Allowed Location Or Not Exist id'
return jsonify(result=False, log=log), 406
return jsonify(result='Not Correct Form'), 404
파일을 저장하려는 위치가 없을 경우, 디렉토리를 생성해주도록 하기 위해 os.system 을 통해 리눅스 커맨드를 실행해줍니다.
filename은 기존 파일명과 동일한 파일이 이미 서버의 동일 경로에 저장된 경우 덮어씌우기 때문에 파일명 뒤에 날짜시간 데이터와 같이 고유한 값을 얹어 변경 후 저장해줍니다.
System.img_meta_update 함수 소스는 아래 3번에서 확인 가능합니다.
3. 이미지 저장 경로 및 파일명 메타 데이터 DB에 저장
location 값은 DB의 상황에 맞게 place 와 room 으로 제한을 두었습니다.
또한, 테이블 구조에 맞게 각 case에 따라 변수들을 예외처리하여 세팅되도록 소스를 작성했습니다.
# vim app/model.py
# ...
class System():
# image meta data update
def img_meta_update(location, id, new_filename):
table_name = False
if location == 'place':
table_name = 'places'
meta_data_column_name = 'imgfile_name'
if location == 'room':
table_name = 'rooms'
meta_data_column_name = 'meta_imgs'
# 정상적인 데이터가 넘어온 경우
if table_name:
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
sql = "SELECT " + meta_data_column_name + " FROM " + table_name + " WHERE " + location + "_id = " + id
print(sql)
cursor.execute(sql)
result = cursor.fetchone()
if result:
origin_meta_data = result[meta_data_column_name]
if origin_meta_data:
new_meta_data = origin_meta_data + ' ' + '/image/' + location + '/' + id + '/' + new_filename
else:
new_meta_data = '/image/' + location + '/' + id + '/' + new_filename
sql = "UPDATE " + table_name + " SET " + meta_data_column_name + " = '" + new_meta_data + "' WHERE " + location + "_id = " + id
print(sql)
cursor.execute(sql)
mysql.connection.commit()
return True
return False
해당 데이터의 이미지로 이미 저장된 부분이 있다면, 기존 데이터를 유지하면서 뒤에 데이터를 추가해주도록 하기 위해
확인하는 작업 & 확인 후 UPDATE 쿼리를 실행하도록 설계했습니다.
메타 데이터 구분은 공백(space)로 진행했습니다.
만약 전송하고자하는 파일 명에 공백(space)가 있을 경우 flask 자체적으로 _ 로 변환하여 저장해줍니다.
예시 : 2203.jpg 파일 업로드 & 2 20 3.jpg 파일 업로드