import os import json from fastapi import FastAPI, UploadFile, File, HTTPException, Form from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse, JSONResponse from fastapi.middleware.cors import CORSMiddleware from pathlib import Path import shutil import uuid app = FastAPI(title="HanSoo Office Editor", version="1.0.0") # CORS 설정 app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 업로드 디렉토리 UPLOAD_DIR = Path("/tmp/hansoo_uploads") UPLOAD_DIR.mkdir(parents=True, exist_ok=True) # 정적 파일 제공 (static 디렉터리가 없으므로 주석 처리) # app.mount("/static", StaticFiles(directory="static"), name="static") @app.get("/") def read_root(): """인덱스 페이지 제공""" return FileResponse("index.html") @app.get("/health") def health_check(): """헬스 체크 엔드포인트""" return {"status": "healthy", "service": "HanSoo Office Editor"} @app.post("/api/upload") async def upload_file(file: UploadFile = File(...)): """파일 업로드 엔드포인트""" try: file_id = str(uuid.uuid4()) file_path = UPLOAD_DIR / f"{file_id}_{file.filename}" with open(file_path, "wb") as buffer: shutil.copyfileobj(file.file, buffer) return { "success": True, "file_id": file_id, "filename": file.filename, "size": file_path.stat().st_size, "content_type": file.content_type } except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.get("/api/files/{file_id}") async def get_file(file_id: str): """업로드된 파일 정보 조회""" files = list(UPLOAD_DIR.glob(f"{file_id}_*")) if not files: raise HTTPException(status_code=404, detail="File not found") file_path = files[0] return { "file_id": file_id, "filename": file_path.name.replace(f"{file_id}_", ""), "size": file_path.stat().st_size } @app.post("/api/process") async def process_file( file_id: str = Form(...), operation: str = Form("extract") ): """파일 처리 엔드포인트 (추출, 변환 등)""" files = list(UPLOAD_DIR.glob(f"{file_id}_*")) if not files: raise HTTPException(status_code=404, detail="File not found") file_path = files[0] try: if operation == "extract": # 텍스트 추출 로직 (확장자에 따라 처리) content = extract_text(file_path) return {"success": True, "content": content} elif operation == "convert": # 변환 로직 return {"success": True, "message": "Conversion completed"} else: raise HTTPException(status_code=400, detail="Unknown operation") except Exception as e: raise HTTPException(status_code=500, detail=str(e)) def extract_text(file_path: Path) -> str: """파일에서 텍스트 추출""" suffix = file_path.suffix.lower() if suffix in [".txt", ".md", ".json", ".csv"]: return file_path.read_text(encoding="utf-8") elif suffix == ".pdf": # PDF 텍스트 추출 (PyPDF2 또는 pdfplumber 필요) return "PDF text extraction requires additional dependencies" elif suffix in [".docx", ".xlsx", ".pptx"]: return "Office file extraction requires python-docx/openpyxl/python-pptx" elif suffix in [".hwp", ".hwpx"]: return "HWP extraction requires rhwp or pyhwp" else: return "Unsupported file format" @app.on_event("shutdown") def cleanup(): """서버 종료 시 업로드 디렉토리 정리""" try: shutil.rmtree(UPLOAD_DIR) except: pass if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", 7860)))