그저 내가 되었고
항해99) 1주차:: 웹개발+ 1주차; 파일 업로드 본문
🔮진행 순서
[1] 생김새 만들기
[2] 준비하기
[3] 서버 만들기
[4] 클라이언트 만들기
[1] 생김새 만들기
1. 사진 파일 입력하는 칸 만들어주기
1) 부트스트랩 컴포넌트(head에)
https://getbootstrap.com/docs/4.0/components/alerts/
2) HTML, CSS - 카드에 이미지 넣기(여기까지 하면 기존의 카드들에 이미지가 달라붙음)
- 부트스트랩 컴포넌트 페이지의 card에서 이미지 태그 찾아 넣기 + static 폴더에 사진 넣고 가져오기
- 코드👇🏻
<div class="card">
<img src="../static/OIKAWA.jpg" class="card-img-top">
<div class="card-body">
<h5 class="card-title">오이카와상,,,</h5>
<p class="card-text">암만 네가 잘나가도,,, 너는 여전히 내 아픈 손가락😭,,,,,</p>
</div>
</div>
3) HTML,CSS - 폼 부분 파일 업로드 넣기(여기까지 하면 Browse 누르고 사진 선택했을 때 그 사진이 선택 창에 들어옴)
<사진 선택하는 칸 만들기>
<div class="custom-file">
<input type="file" class="custom-file-input" id="customFile">
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
요👆🏻코드를 넣으면 사진 선택하는 칸이 생김.(아래 이미지에서 [사진 선택하기] 요 칸.이걸 적으면 바로 Browse 눌러서 사진 선택 '만' 가능, 아직 선택 창에는 안들어옴) id는 customFile에서 그냥 file(F 말고 f!!!!!!!!)
이걸 어디에 적어줘야하나면, 일단... body의 class 기준으로.
가장~~~~! 바깥에 wrap class가 jumbotron-fluid(저 백그라운드의 회색 직사각형 박스)와 card-colums(저장하기 눌러서 만든 각각의 카드들 전부 들어있는 클래스) 두 개를 갖고 있음.
그리고 jumbotron-fluid 안에 container class가 있고, 걔가 두 개의 하위 클래스(h1-나홀로 일기장-)과 posting-box 데리고 있음. 그리고 posting-box 안에 form-group(사진 제목 입력칸), form-group(내용 입력칸), button(저장하기)) 세 개를 품고 있음. 우리는 여기에! 사진 제목 입력칸 위에!!!!! 사진 업로드 창을 만들거니까, 그 위치에 코드를 집어 넣으면 됨.
아래👇🏻는 다 붙여 넣은 body의 wrap class 전체!!
<div class="wrap">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1>나홀로 일기장</h1>
<div class="posting-box">
<div class="custom-file">
<input type="file" class="custom-file-input" id="file">
<label class="custom-file-label" for="file">사진 선택하기</label>
</div>
<div class="form-group">
<input type="email" class="form-control" id="title" aria-describedby="emailHelp"
placeholder="사진 제목">
</div>
<div class="form-group">
<textarea class="form-control" id="content" rows="3"
placeholder="내용 입력"></textarea>
</div>
<button onclick="posting()" type="button" class="btn btn-primary">저장하기</button>
</div>
</div>
</div>
<div class="card-columns" id="cardsbox">
<div class="card">
<img class="card-img-top" src="../static/OIKAWA.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">오이카와,,,</h5>
<p class="card-text">암만 네가 잘나가도,,, 너는 여전히 내 아픈 손가락😭,,,,,</p>
</div>
</div>
</div>
<선택한 사진이 선택하기 창에 들어오게 하기>
그리고, 여기서 파일업로드 라이브러리를 임포트👇🏻 해야만 선택한 파일이 사진 선택하기 창에 들어옴!!!(head에 작성)
<script src="https://cdn.jsdelivr.net/npm/bs-custom-file-input/dist/bs-custom-file-input.js"></script>
임포트 후, (document).ready에 한 줄 추가 필요
bsCustomFileInput.init()
위의 코드 적을거고, 결론적으로 이렇게👇🏻 됨.
<script>
$(document).ready(function () {
bsCustomFileInput.init()
listing()
})
function listing() {
$.ajax({
type: "GET",
...
여기까지 하면, 이게👇🏻 가능.
[2] 준비하기
1. 서버 쪽에서 파일 받기 코드 먼저 작성
save_to = 'static/mypicture.jpg'
file.save(save_to)
👆🏻이거고(static이라는 경로 안에, mypicture.jpg라는 이름으로 저장 들어 간다는 뜻)
@app.route('/memo', methods=['POST'])
👆🏻이 부분에 붙을 것.
결과로 👇🏻이렇게 됨~!
@app.route('/diary', methods=['POST'])
def save_diary():
title_receive = request.form["title_give"]
content_receive = request.form["content_give"]
file = request.files["file_give"]
save_to = 'static/mypicture.jpg'
file.save(save_to)
doc = {
'title': title_receive,
'content': content_receive,
}
db.diary.insert_one(doc)
return jsonify({'msg': '저장 완료!'})
2. 클라이언트 쪽에서 파일 보내기 코드 작성
function posting() {
let title = $('#title').val()
let content = $("#content").val()
let file = $('#file')[0].files[0]
let form_data = new FormData()
form_data.append("file_give", file)
form_data.append("title_give", title)
form_data.append("content_give", content)
$.ajax({
type: "POST",
url: "/diary",
data: form_data,
cache: false,
contentType: false,
processData: false,
success: function (response) {
alert(response["msg"])
window.location.reload()
}
});
}
👆🏻이거고(기존의 맨 위의 두 줄 let title=~이랑 let content=~는 그대로 두고, 그 밑에... 새로 form_data.append로 파일 덕분에.. form_data라는 것에 실려져 보내짐(file은 그냥은 못 가고 꼭 form_data에 실려져 가야됨)
+) $('#file')[0].files[0] 왜 이렇게 복잡?! $('#file')[0]얘는 여기서 그냥 file 찍으면.. 우리가 body에서 id값 붙인 여기<input type="file" class="custom-file-input" id="file">가 많은 속성을 달고 있기 때문에 [0]을 딱 명시해줘야! 우리가 body에 적어준 그대로(<input type="file" class="custom-file-input" id="file">이렇게) 찍힘(콘솔창에서 확인 가능).
뒤의 $('#file')[0].files[0] 이거는.. 없이 찍어보면 들어가 있는 files의 갯수가 나옴. 그렇기에 [0]을 찍어주면 방금 업로드한 파일이 선택됨
+) 파일 보낼 때 기본 속성이 최적화 되어 있지 않을 수 있기 때문에 👇🏻얘로 다 꺼주는 것
cache: false,
contentType: false,
processData: false,
function posting() {
여기 밑에 붙을 것.
결과로 👇🏻이렇게 됨~!(기존의.. 텍스트만 입력하는 post는 삭제ㄱㄱ~!)
function posting() {
let title = $('#title').val()
let content = $("#content").val()
let file = $("#file")[0].files[0]
let form_data = new FormData()
form_data.append("file_give", file)
form_data.append("title_give", title)
form_data.append("content_give", content)
$.ajax({
type: "POST",
url: "/diary",
data: form_data,
cache: false,
contentType: false,
processData: false,
success: function (response) {
alert(response["msg"])
window.location.reload()
}
});
}
[3] 서버 만들기
🔮새롭고 Fancy한 문법 두 개 연습
1. f-string
myname = '홍길동'
text = f'내 이름은 {myname}입니다.'
(text = '내 이름은' + {myname} +.... 이렇게 지저분하게 안써도 됨ㅎㅅㅎ)
2. datetime
from datetime import datetime
👆🏻임포트
now = datetime.now()
print(now)
👆🏻자주 쓰는 문법 1)지금 날짜 시간 찍기
today = datetime.now()
mytime = today.strftime("%Y-%m-%d-%H-%M-%S")or("%년-%월-%일-%시-%분-%초") //쓸 만큼 잘라 쓰기
print(mytime)
👆🏻자주 쓰는 문법 2)날짜 시간을 원하는 형태로 변환하기
위의 것 갑자기 왜,,,,,?
받을 image file 이름을 시-분-초까지 나오게 해서 겹칠 일 없도록 하자!(이름이 같은-예컨대 원래 했던 mypicture- 파일로 계속 저장? 그러면 계속 파일이 덧씌워지겠쥬,,, 안되자나염,,,,!!!)
그래서 결국 하고싶은건? 파일 이름을 이렇게👇🏻 지정해주려구~!
today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')
filename = f'file-{mytime}'
(👆🏻이거 print(filename)으로 실행하면 file-2022-09-19-20-06-40 일케 뜬당!!!!)
그러면 차례대로!!
1) app.py(서버)에 임포트 먼저 해주고
from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client.dbsparta_plus_week1
from datetime import datetime
@app.route('/')
def home():
return render_template('index.html')
2) 새로운 이름 만들어주고
@app.route('/diary', methods=['POST'])
def save_diary():
title_receive = request.form["title_give"]
content_receive = request.form["content_give"]
file = request.files["file_give"]
today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')
filename = f'file-{mytime}'
db.diary.insert_one(doc)
return jsonify({'msg': '저장 완료!'})
3) 새로운 이름으로 저장해주고
@app.route('/diary', methods=['POST'])
def save_diary():
title_receive = request.form["title_give"]
content_receive = request.form["content_give"]
file = request.files["file_give"]
today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')
filename = f'file-{mytime}'
save_to = f'static/{filename}.jpg'
file.save(save_to)
doc = {
'title': title_receive,
'content': content_receive,
}
db.diary.insert_one(doc)
return jsonify({'msg': '저장 완료!'})
4) jpg 말고 다른 이미지 파일도 있으니까,,,,, 확장자 추가해주자~!
extension = file.filename.split('.')[-1]
👆🏻요걸 app.py에 추가할건데(POST란), 확장자는 파일 네임의 가장 마지막 닷(.) 뒤의 글자들이니까!!! 저렇게 생겼당.
그리구 이제 같은 란의 좀 밑의 save_to에서 jpg 대신에 extension을 적음 된당. 이렇게!!! 👇🏻
extension = file.filename.split('.')[-1]
today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')
filename = f'file-{mytime}'
save_to = f'static/{filename}.{extension}'
file.save(save_to)
5) mongodb가 우리가 저장하려는 사진이 각각 어떤 title과 content에 대응하는지 알아야 하니까👇🏻 마지막 한 줄 추가~!
doc = {
'title': title_receive,
'content': content_receive,
'file' : f'{filename}.{extension}'
}
[4] 클라이언트 만들기
👉🏻우리가 저장한 사진들이 뜨도록~!(지금은,, 아직 고정된 img로 보여주고 있음)
1. 우선적으로, index.html의 listing()에 아래👇🏻 세 번째 줄의 코드 추가
let title = diaries[i]['title']
let content = diaries[i]['content']
let file = diaries[i]['file']
2. 아래의 let temp_html의 img class의 img src 바꿔주기!!!
let temp_html = `<div class="card">
<img class="card-img-top" src="../static/'OIKAWA.png' alt="Card image cap">
👇🏻
let temp_html = `<div class="card">
<img class="card-img-top" src="../static/${file}" alt="Card image cap">
3. 추가로 작성 날짜 같이 저장되게?!(약간 흐리게!!)
date_receive = today.strftime('%Y-%m-%d')
doc = {
'title': title_receive,
'content': content_receive,
'file' : f'{filename}.{extension}',
'date' : date_receive
}
let date = diaries[i]['date']
let temp_html = `<div class="card">
...
<p class="date" id="date">${date}</p>
...
$('#cardsbox').append(temp_html)
.date {
opacity: 0.4;
}
결과물:::
최애는 최애고.... 오이카와는 오이카와니까..........💙
'개발 > 항해99 9기' 카테고리의 다른 글
항해99) 1주차:: 웹개발+ 2주차; SSR(Server Side Rendering) WORDBOOK 전체 코드 (0) | 2022.09.21 |
---|---|
항해99) 1주차:: 웹개발+ 2주차; SSR(Server Side Rendering) (0) | 2022.09.21 |
📚지금까지 헷갈리는 것 정리 (0) | 2022.09.09 |
항해99) 웹종 5주차 웹서비스 런칭 (0) | 2022.09.06 |
항해99) 웹종 4주차 [스파르타피디아] POST & GET 한 장 정리🤜🏻 (0) | 2022.09.06 |