form 태그에서 file upload 하기 위해선 html에서 enctype="multipart/form-data"과 type="file"이 필요하다.
아래는 예시 코드이다.
//write.html
<form action="/api/new" method="POST" enctype="multipart/form-data">
<label for="photo">이미지 첨부 :</label>
<input type="file" id="photo" name="photo_give" required><br><br>
백엔드에서는 python에서 file을 전송할 때 사용되는 세가지 라이브러리를 import 해야 한다.
import certifi
import base64 // 데이터를 base64 형식으로 인코딩 또는 디코딩 해주는 모듈
import gridfs // 대용량 파일을 저장하고 검색하기 위해 사용, 파일을 작은 청크 단위로 나누어 저장하므로 대용량 파일을 처리하는데 유용
아래는 백엔드 예시 코드이다.
//app.py
@app.route("/api", methods=["GET"])
def home_get():
all_myself = list(db.myself.find({},{'_id':True, 'name':True, 'mbti':True, 'introduction':True,
'strengths':True, 'collaboration_style':True ,'blog_url':True
,'github_url':True, 'photo':True}))
for myself in all_myself:
photo_id = myself['photo']
if photo_id: // photo_id가 있을 때
try:
image_data = fs.get(photo_id).read() // gridFs가 해당 파일을 바이너리 데이터로 읽어온다. image_data에 해당 바이너리 데이터가 저장된다.
base64_img = base64.b64encode(image_data).decode('utf-8') // base64 형식으로 image_date 인코딩, 인코딩된 데이터를 utf-8 형식으로 디코딩하여 문자열로.
myself['photo'] = 'data:image/jpeg;base64,' + base64_img // URI 형식으로 재구성하여 이미지 데이터를 텍스트로 포함한 뒤 photo 필드에 저장
except gridfs.error.NoFile as e:
print.error("파일이 없습니다.")
myself['_id'] = str(myself['_id'])
return jsonify({'result':all_myself})
@app.route("/api/new", methods=["POST"])
def post_write():
photo_receive = request.files['photo_give']
name_receive = request.form['name_give']
mbti_receive = request.form['mbti_give']
introduction_receive = request.form['introduction_give']
strengths_receive = request.form['strengths_give']
collaboration_style_receive = request.form['collaboration-style_give']
blog_url_receive = request.form['blog-url_give']
github_receive = request.form['github-url_give']
file_img_id = fs.put(photo_receive) // 이 부분이 gridFS로 파일을 DB에 저장해주는 부분.
doc = {
'photo' : file_img_id,
'name' : name_receive,
'mbti' : mbti_receive,
'introduction' : introduction_receive,
'strengths' : strengths_receive,
'collaboration_style' : collaboration_style_receive,
'blog_url' : blog_url_receive,
'github_url' : github_receive
}
db.myself.insert_one(doc)
return redirect('/')
인코딩 & 디코딩이란
어느날 아침 사용자가 문자열 데이터를 컴퓨터에게 던져줬다.
컴퓨터는 그 데이터를 이해하지 못하기 때문에 바이트코드로 변경시켜줘야 한다.
이때 인코딩이 등장한다.
인코딩 : 그 문자열 가져와 내가 바이트 코드로 변경해서 컴퓨터 너가 이해할 수 있게 해줄게
컴퓨터 : 고마워
그렇게 며칠 후 사용자는 인코딩된 데이터를 필요로 하는데..
컴퓨터 : 어떡하지..
디코딩 : 컴퓨타씨 저에게 맡겨주시죠.. 제가 문자열로 바꿔드리겠습니다
컴퓨터 : 감사합니다!
이렇게 되어 사용자는 무사~히 데이터를 검색하거나 저장할 수 있게 되었다~~~
base64는 데이터를 64개의 문자로 구성된 ASCII 문자열로 변환하는 방식이다.
데이터 URI 형식으로 file 데이터를 저장한다는 것은 파일 데이터를 문자열로 포함시켜 저장한다는 의미이다.
이렇게 함으로써 여러가지 장점이 있을 수 있는데 가장 큰 장점은 파일 데이터를 문자열로 다룬다는 것이다.
파일 데이터를 파일 경로로 사용하는 것보다 데이터 URI로 사용하는 것이 좋은 이유는 아래와 같다.
1. 파일 경로가 변경되면 사용하고 있는 파일 경로를 변경해줘야 한다.
사용자 : 오랜만에 옛날에 써놓은 블로그나 볼까? 어라? 이미지가 왜 다 안보여!!
컴퓨터 : 파일의 경로가 변경되어 발생하는 문제입니다.
사용자 : 헐.. 파일들 이미 다 삭제했는데?? 그럼 볼 수 없는거야?
컴퓨터 : 네
사용자 : ...
2. 파일 경로가 직접 노출되므로 보안상 위험하다.
해커 : 후후훗.. 멍청한 녀석 파일 경로 직접 사용했잖아? 해킹해주겠어 !
사용자 : 어? 뭐야 갑자기 컴퓨터가 이상해!