8비트 이진 데이터를 문자 코드에 영향받지 않는 ASCII 문자열로 바꾸어 인코딩하는 방식
위에 'For use in < img > elements'처럼 인코딩하면 이미지를 텍스트로 표현 할 수 있다.
DB에 이미지를 넣는 방식은 서버에 이미지를 직접 넣지 않는 장점이 있다.
인코딩한 텍스트를 DB에 넣고 쓸 땐 불러와 화면에 < img> 형식으로 뿌리면 매우 간단한 구현이 가능하다.
브라우저가 이미지 랜더링 시, base64로 표현할 경우 문서로딩과 같이 로딩되기에 끊기지 않고 불려온다.
256가지를 표현할 수 있는 바이트를 64가지를 사용해서 표현하기 떄문이다.
다시 말해, 8비트를 6비트로 표현하는 것이다.
따라서 Base64 인코딩을 사용하면 원본보다 대략 33%의 크기 증가가 발생한다.
사진의 크기가 크다면, 태그에 매우긴 텍스트가 보이기떄문에 가동성에 어려움을 준다
나는 2번 방법을 사용했다
1번은 https://taehyeki.tistory.com/153 에서 한 번 보시고 시도 해보세요
통상 적으로 3번을 많이 쓰지만...
내가 하는 프로젝트는 일주일만 하는 미니프로젝트라 과감하게 PASS...
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
from pymongo import MongoClient
import certifi
ca=certifi.where()
client = MongoClient('MongoDB Altas URL주소 넣으세요', tlsCAFile=ca)
db = client.<DB테이블명>
####### 1 #######
import base64
import gridfs
fs = gridfs.GridFS(db)
# 메인 페이지
@app.route('/')
def home():
return render_template('index.html')
# Post 요청 API: 식당 저장
@app.route('/restaurant', methods=["POST"])
def restaurant_post():
placeName_receive = request.form['placeName_give']
address_receive = request.form['address_give']
####### 2 #######
picture_receive = request.files['picture_give']
star_receive = request.form['star_give']
review_receive = request.form['review_give']
#print(placeName_receive,address_receive,picture_receive,star_receive,review_receive)
####### 3 #######
# GridFs를 통해 파일을 분할하여 DB에 저장
file_img_id = fs.put(picture_receive)
# DB에 저장
doc = {
'name': placeName_receive,
'address': address_receive,
'picture': file_img_id,
'star': star_receive,
'review': review_receive
}
db.<DB테이블명>.insert_one(doc)
return jsonify({'result': 'success', 'msg': '저장완료'})
GET 요청 API
@app.route("/restaurant", methods=["GET"])
def restaurant_get():
# 데이터 모두 가져오기
all_restaurants = list(db.<DB테이블명>.find({}, {'_id': False}))
# 이미지 데이터 검색 및 인코딩
for restaurant in all_restaurants:
picture_id = restaurant['picture'] # ObjectId
if picture_id:
try:
# ObjectId를 사용하여 이미지 데이터 검색
image_data = fs.get(picture_id).read()
# 이미지 데이터를 base64로 인코딩 및 디코딩
base64_img = base64.b64encode(image_data).decode('utf-8')
# 'picture' 필드 업데이트
restaurant['picture'] = base64_img
except gridfs.errors.NoFile as e:
# 이미지 데이터를 가져오지 못한 경우 예외처리
print("요구하신 파일이 존재하지 않습니다")
return jsonify({'result': all_restaurants})
주석으로 이해 했을거라 믿습니다....
농담이고요.. 중요한 코드만 따로 설명 하겠습니다
####### 1 #######
import base64
import gridfs
fs = gridfs.GridFS(db)
-> db와 연결시킨 fs를 만들어준다
####### 2 #######
picture_receive = request.files['picture_give']
form이 아닌 files를 받아야 하는게 핵심이다
그럴러면 Front-end쪽도 손을 봐줘야 한다
잠시만 Front-end 부분으로 가겠습니다!!!
let input = document.querySelector('#FileName');
formData.append("picture_give", input.files[0]);
일반적이게 받는 법이랑 비교를 해볼까요?
let address = $('#addrName').val();
formData.append("address_give", address);
많이 다릅니다... 꼭 꼭 유의하세요...
저 삽집 많이 했습니다... ㅜㅜ
다시 Back-end 부분으로 돌아 옵시다!!
app.py으로 돌아가세요!!
####### 3 #######
file_img_id = fs.put(picture_receive)
GridFs를 통해 파일을 분할하여 DB에 저장하는데
그러면 아래의 두개의 폴더가 생성이 된다
맨위에 사이트에서 맥도날드사진을 base 64으로 한 사진에 'For use as CSS background'에 있는 값인 4AAQS...이랑 같은 값이라는 걸 알수 있다.
위에 3개의 파일을 보면 ObjectId가 일치한다. 그래서 모두 연결되어있다고 봐도 무방하다.
DB에 넣는건 아주 쉬운데 불러오는건 살짝 난이도가 올라간다.
all_restaurants = list(db.<DB테이블명>.find({}, {'_id': False}))
for restaurant in all_restaurants:
picture_id = restaurant['picture'] # ObjectId
if picture_id:
try:
image_data = fs.get(picture_id).read()
base64_img = base64.b64encode(image_data).decode('utf-8')
restaurant['picture'] = base64_img
except gridfs.errors.NoFile as e:
print("요구하신 파일이 존재하지 않습니다")
return jsonify({'result': all_restaurants})
일단 저는 Properties중에서 사진부분만 불러오면 되는 상황입니다.
all_restaurants에 디비에 있는 모든걸 불러옵니다.
그런 다음 for loop으로 돌립니다.
restaurant['picture']는 ObjectId가 담아 있어서 picture_id에 담아주고요
만약 존재 한다고 손상된 이미지 파일이 아니면
fs.get()을 통해 바이너리 데이터를 얻습니다.
만약 손상된 이미지 파일이라면 gridfs.errors.NoFile으로 예외처리가 됩니다.
바이너리 데이터를 얻었으면 인코딩 디코딩 과정을 걸치고
ObjectId값이 담아 있던 restaurant['picture']에 디코딩된 값을 넣어줍니다.
마지막으로 프론트엔드쪽으로 jsonify로 넘겨주면 끝!!
고의적으로 확장자를 image 확장자로 바꾼건 예외처리가 안됩니다.
데이터 크기를 제한하는 것은 상황과 요구사항에 따라 다를 수 있으며, 데이터의 중요성, 대역폭 제한, 전송 속도 등을 고려해야 합니다. 특히 네트워크 통신이나 저장 공간이 제한된 환경에서는 데이터 크기를 최소화하는 방법을 고려해야 합니다.
저는 사진을 사용할 목적은 단순 웹사이트에 식당 사진을 첨부 하는거라서 고해상도 이미지 파일은 필요가 없습니다.
그래서 적당한 이미지 사이즈 범위를 설정할 수 있습니다. 이는 일반적인 웹 환경에서 사용하기 위한 추천 범위이며, 상황에 따라 조정될 수 있습니다.
따라서, 웹사이트에서 식당 사진을 첨부할 때는 다음과 같은 이미지 사이즈 범위를 고려할 수 있습니다: