DB에 사진 업로드하고 화면에 나타내기HTML+CSS+JS+Flask/파일 업로드 기능2022. 5. 9. 15:33
Table of Contents
What to do?
- 이미지 업로더로 이미지를 프로젝트 static 폴더 내에 저장하고 DB에 이미지의 이름, 코멘트, static 폴더에 저장할 이미지의 이름과 확장자를 DB에 저장한 후 이를 이용해서 static 폴더내에 저장된 이미지를 불러와서 화면에 나타내보자!
- file은 일반 json 형식의 데이터와 다르게 formdata 형식으로 넣어서 보내자!
- static 폴더에 저장된 이미지 이름이 겹치면 안되므로 이미지 이름을 datetime 함수를 이용해서 날짜-시간으로 저장해주자!!
예시화면
순서
1-1. 클라이언트가 파일을 서버에 보내는 코드를 작성
- Tip. 파일을 서버에 보낼때는 일반 JSON 형식의 파일이 아닌 formdata에 데이터를 넣어서 POST 요청으로 보낸다!
- Tip. 클라이언트가 POST 요청을하면 페이지를 새로고침한다
function posting() {
let title = $('#img-title').val()
let comment = $("#img-comment").val()
let file = $('#img-file')[0].files[0]
// form data에 데이터 저장
let form_data = new FormData()
form_data.append("file_give", file)
form_data.append("title_give", title)
form_data.append("comment_give", comment)
$.ajax({
type: "POST",
url: "/posting",
// form data 형식으로 파일 데이터 보내기
data: form_data,
cache: false,
contentType: false,
processData: false,
success: function (response) {
alert(response["msg"])
window.location.reload()
}
});
}
1-2. 서버에서 클라이언트가 보낸 이미지를 static 폴더에 저장하고 데이터를 DB에 저장하는 API (POST)
- Tip. static 폴더에 저장된 이미지 이름이 겹치면 안되므로 이미지 이름을 datetime 함수를 이용해서 날짜-시간으로 저장해주고 확장자명도 같이 저장하자!!!
- Tip. f-string을 이용해 코드를 간결하게 사용하자
- Tip. formdata에서 파일 가져올 때는 request.files 사용하기
# 클라이언트가 서버에 이미지 정보 업로드
@app.route('/posting', methods=['POST'])
def posting():
title_receive = request.form["title_give"]
comment_receive = request.form["comment_give"]
file = request.files["file_give"]
# static 폴더에 저장될 파일 이름 생성하기
today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')
filename = f'file-{mytime}'
# 확장자 나누기
extension = file.filename.split('.')[-1]
# static 폴더에 저장
save_to = f'static/{filename}.{extension}'
file.save(save_to)
# DB에 저장
doc = {
'title': title_receive,
'comment': comment_receive,
'file': f'{filename}.{extension}'
}
db.image.insert_one(doc)
return jsonify({'msg': '업로드 완료!'})
2-1. DB에서 이미지 데이터를 가져오는 API (GET)
- 서버에서 static 폴더에 저장된 이미지 이름 등 모든 이미지의 정보를 불러온다
# 서버에서 이미지 정보 가져오기
@app.route('/listing', methods=['GET'])
def listing():
images = list(db.image.find({}, {'_id': False}))
return jsonify({'result': 'success', 'images': images})
2-2. 클라이언트가 서버에서 이미지에 대한 데이터를 가져오는 코드
- Tip. 페이지가 새로고침 될 때마다 GET 요청으로 이미지에 대한 정보를 서버에서 받아와서 static 폴더에 있는 이미지를 img 태그에 넣어서 화면에 띄운다!
- Tip. jquery append 함수 사용
$(document).ready(function () {
listing();
})
function listing() {
$.ajax({
type: "GET",
url: "/listing",
data: {},
success: function (response) {
if (response["result"] == "success") {
let images = response['images']
for (let i = 0; i < images.length; i++) {
let title = images[i]['title']
let comment = images[i]['comment']
let file = images[i]['file']
let date = file.substr(5, 13)
console.log(file)
let temp_html =
`<div class="col">
<div class="card h-100">
<img src="../static/${file}" class="card-img-top" style="max-height: 300px">
<div class="card-body">
<h5 class="card-title">${title}</h5>
<p class="card-text">${comment}</p>
</div>
<div class="card-footer">
<small class="text-muted">${date}</small>
</div>
</div>
</div>`
$('#cards-box').append(temp_html)
}
}
}
});
}
전체 소스코드
app.py
from flask import Flask, render_template, request, jsonify
from pymongo import MongoClient # pymongo를 임포트 하기
from datetime import datetime
client = MongoClient(
'mongodb+srv://duck:1234@cluster0.8lepp.mongodb.net/Cluster0?retryWrites=true&w=majority') # Atlas에서 가져올 접속 정보
db = client.images # 'image'라는 이름의 db로 접속한다. 만약 없으면 자동으로 생성한다.
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
# 클라이언트가 서버에 이미지 정보 업로드
@app.route('/posting', methods=['POST'])
def posting():
title_receive = request.form["title_give"]
comment_receive = request.form["comment_give"]
file = request.files["file_give"]
# static 폴더에 저장될 파일 이름 생성하기
today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')
filename = f'file-{mytime}'
# 확장자 나누기
extension = file.filename.split('.')[-1]
# static 폴더에 저장
save_to = f'static/{filename}.{extension}'
file.save(save_to)
# DB에 저장
doc = {
'title': title_receive,
'comment': comment_receive,
'file': f'{filename}.{extension}'
}
db.image.insert_one(doc)
return jsonify({'msg': '업로드 완료!'})
# 서버에서 이미지 정보 가져오기
@app.route('/listing', methods=['GET'])
def listing():
images = list(db.image.find({}, {'_id': False}))
return jsonify({'result': 'success', 'images': images})
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)
templates/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<title>부트스트랩 템플릿</title>
<link href="https://fonts.googleapis.com/css2?family=Jua&display=swap" rel="stylesheet">
<style>
* {
font-family: 'Jua', sans-serif;
}
.wrap {
margin: auto;
width: 900px;
}
.title {
background-color: gainsboro;
padding: 20px 30px;
}
.form-group {
margin: 10px 0;
}
.posting-box {
margin: 10px auto 30px auto;
width: 500px;
border: 3px solid black;
border-radius: 5px;
padding: 25px;
}
</style>
<script>
$(document).ready(function () {
listing();
})
function listing() {
$.ajax({
type: "GET",
url: "/listing",
data: {},
success: function (response) {
console.log(response["result"])
if (response["result"] == "success") {
let images = response['images']
for (let i = 0; i < images.length; i++) {
let title = images[i]['title']
let comment = images[i]['comment']
let file = images[i]['file']
let date = file.substr(5, 13)
console.log(file)
let temp_html =
`<div class="col">
<div class="card h-100">
<img src="../static/${file}" class="card-img-top" style="max-height: 300px">
<div class="card-body">
<h5 class="card-title">${title}</h5>
<p class="card-text">${comment}</p>
</div>
<div class="card-footer">
<small class="text-muted">${date}</small>
</div>
</div>
</div>`
$('#cards-box').append(temp_html)
}
}
}
});
}
// 서버에 이미지 정보 올리기
function posting() {
let title = $('#img-title').val()
let comment = $("#img-comment").val()
let file = $('#img-file')[0].files[0]
let form_data = new FormData()
form_data.append("file_give", file)
form_data.append("title_give", title)
form_data.append("comment_give", comment)
$.ajax({
type: "POST",
url: "/posting",
// form data 형식으로 파일 데이터 보내기
data: form_data,
cache: false,
contentType: false,
processData: false,
success: function (response) {
alert(response["msg"])
window.location.reload()
}
});
}
</script>
</head>
<body>
<div class="wrap">
<div class="title">
<h1 class="display-4">파일 업로드</h1>
<hr class="my-4">
<div class="posting-box" id="post-box">
<!--이미지 업로더-->
<div class="custom-file">
<input type="file" class="custom-file-input" id="img-file">
<label class="custom-file-label" for="img-file">Choose file</label>
</div>
<!--이미지 제목 및 코멘트-->
<div class="form-group">
<label>사진 제목</label>
<input type="email" class="form-control" aria-describedby="emailHelp"
id="img-title" placeholder="">
</div>
<div class="form-group">
<label>간단 코멘트</label>
<input type="email" class="form-control"
id="img-comment" placeholder="">
</div>
<button type="submit" onclick="posting()" class="btn btn-primary">업로드하기</button>
</div>
</div>
<div class="row row-cols-1 row-cols-md-3 g-4" id="cards-box">
</div>
</div>
</body>
</html>
'HTML+CSS+JS+Flask > 파일 업로드 기능' 카테고리의 다른 글
파일 업로드 / 속성값(jquery) (0) | 2022.05.09 |
---|
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!