- 일일 공수 입력 기능 - 부적합 사항 등록 (이미지 선택사항) - 날짜별 부적합 조회 (시간순 나열) - 목록 관리 (인라인 편집, 작업시간 확인 버튼) - 보고서 생성 (총 공수/부적합 시간 분리) - JWT 인증 및 권한 관리 - Docker 기반 배포 환경 구성
62 lines
1.9 KiB
Python
62 lines
1.9 KiB
Python
import os
|
|
import base64
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
import uuid
|
|
from PIL import Image
|
|
import io
|
|
|
|
UPLOAD_DIR = "/app/uploads"
|
|
|
|
def ensure_upload_dir():
|
|
"""업로드 디렉토리 생성"""
|
|
if not os.path.exists(UPLOAD_DIR):
|
|
os.makedirs(UPLOAD_DIR)
|
|
|
|
def save_base64_image(base64_string: str) -> Optional[str]:
|
|
"""Base64 이미지를 파일로 저장하고 경로 반환"""
|
|
try:
|
|
ensure_upload_dir()
|
|
|
|
# Base64 헤더 제거
|
|
if "," in base64_string:
|
|
base64_string = base64_string.split(",")[1]
|
|
|
|
# 디코딩
|
|
image_data = base64.b64decode(base64_string)
|
|
|
|
# 이미지 검증 및 형식 확인
|
|
image = Image.open(io.BytesIO(image_data))
|
|
format = image.format.lower() if image.format else 'png'
|
|
|
|
# 파일명 생성
|
|
filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:8]}.{format}"
|
|
filepath = os.path.join(UPLOAD_DIR, filename)
|
|
|
|
# 이미지 저장 (최대 크기 제한)
|
|
max_size = (1920, 1920)
|
|
image.thumbnail(max_size, Image.Resampling.LANCZOS)
|
|
|
|
if format == 'png':
|
|
image.save(filepath, 'PNG', optimize=True)
|
|
else:
|
|
image.save(filepath, 'JPEG', quality=85, optimize=True)
|
|
|
|
# 웹 경로 반환
|
|
return f"/uploads/{filename}"
|
|
|
|
except Exception as e:
|
|
print(f"이미지 저장 실패: {e}")
|
|
return None
|
|
|
|
def delete_file(filepath: str):
|
|
"""파일 삭제"""
|
|
try:
|
|
if filepath and filepath.startswith("/uploads/"):
|
|
filename = filepath.replace("/uploads/", "")
|
|
full_path = os.path.join(UPLOAD_DIR, filename)
|
|
if os.path.exists(full_path):
|
|
os.remove(full_path)
|
|
except Exception as e:
|
|
print(f"파일 삭제 실패: {e}")
|