파일을 받아 안전하게 저장한다 — POST /files
박수현 · (사)한국정보공학기술사회 · 2026
POST /files 로 다중 수신uploads/ 에 저장🎯 목표: 신뢰할 수 없는 입력(업로드)을 검증·저장까지 안전하게.
request.files 로 수신@app.post("/files")
def upload():
uploaded = request.files.getlist("file") # 여러 개
if not uploaded:
return jsonify({"error": "파일이 없습니다"}), 400
results = []
for f in uploaded:
# … 검증 → 저장 → (색인) …
results.append({"filename": f.filename})
return jsonify(results)
getlist("file") — 다중 업로드 지원📁 전체:
8.web_app/5.file_manager_restapi/app.py
from werkzeug.utils import secure_filename
ALLOWED = {".pdf", ".txt"} # DOCX 는 한 줄로 확장 가능
def save_upload(f):
if not f or f.filename == "": # 빈 파일 거부
raise ValueError("파일이 선택되지 않았습니다")
name = secure_filename(f.filename) # 경로 조작 방지
ext = os.path.splitext(name)[1].lower()
if ext not in ALLOWED: # 허용 형식만
raise ValueError(f"지원하지 않는 형식: {ext}")
path = os.path.join("uploads", name)
f.save(path) # 저장만 — 색인은 다음 단계
return path
secure_filename — ../../etc/passwd 류 경로 조작 차단filename == "")도 즉시 거부⚠️ 업로드는 외부 입력이므로 항상 검증한다. 크기 제한(
MAX_CONTENT_LENGTH)도 권장. 📎 DOCX 확장:ALLOWED에.docx추가,Docx2txtLoader분기 추가로 대응.
[
{"filename": "faq.pdf",
"status": "saved",
"chunks": 42},
{"filename": "rule.txt",
"status": "saved",
"chunks": 18}
]
🔑 프론트엔드는 이 JSON 으로 목록·진행상태를 표시한다.
💡 이번 단계의 범위는 수신·검증·저장까지다. 청킹·임베딩(색인)은 다음 회차에서 다루며,
chunk 수는 색인 단계에서 채워진다.
request.filesPOST /files + getlist 로 여러 개 동시 업로드secure_filename 으로 경로 조작 차단