Files
doc_ai/workspace/api.py
2025-06-12 12:33:07 +09:00

128 lines
3.8 KiB
Python

# api.py
import asyncio
import json # JSON 파싱을 위해 추가
from fastapi import APIRouter, FastAPI, HTTPException, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from routers import google_docai
from utils.config import (
CORS_ALLOW_CREDENTIALS,
CORS_ALLOW_HEADERS,
CORS_ALLOW_METHODS,
CORS_ALLOW_ORIGINS,
DOCAI_LOCATION,
DOCAI_PROJECT_ID,
UPLOAD_DOCS_DIR,
)
# 유틸리티 함수 임포트 (기존 코드 유지)
from utils.file_utils import (
create_essential_directories,
create_key,
save_uploaded_file,
)
app = FastAPI()
# CORS 설정 (기존 코드 유지)
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOW_ORIGINS,
allow_credentials=CORS_ALLOW_CREDENTIALS,
allow_methods=CORS_ALLOW_METHODS,
allow_headers=CORS_ALLOW_HEADERS,
)
# 애플리케이션 시작 시 실행될 함수 (기존 코드 유지)
@app.on_event("startup")
async def startup_event():
print("Starting up...")
create_essential_directories()
print("Essential directories created.")
# --- Document AI 라우터 ---
doc_ai_router = APIRouter(
prefix="/docai",
tags=["DocumentAI"],
)
# Document AI 관련 설정값 (프로덕션에서는 환경 변수나 설정 파일에서 로드 권장)
# DOCAI_PROCESSOR_ID = "b838676d4e3b4758" # 실제 사용자의 프로세서 ID
# KEC_DOCAI_PROCESSOR_ID = "94de4322c20d276f"
async def run_sync_in_threadpool(func, *args, **kwargs):
"""동기 함수를 별도의 스레드에서 실행하고 await 가능하게 만듭니다."""
loop = asyncio.get_event_loop()
if hasattr(asyncio, "to_thread"): # Python 3.9+
return await asyncio.to_thread(func, *args, **kwargs)
else: # Python < 3.9
return await loop.run_in_executor(None, lambda: func(*args, **kwargs))
@doc_ai_router.post("/available-processors", summary="도면 OCR API")
async def handle_docai_upload(file: UploadFile, processor_id: str):
"""
국토교통부 = "b838676d4e3b4758"\n
도로공사 = "94de4322c20d276f"
"""
if not file.content_type:
raise HTTPException(status_code=400, detail="File content type is missing.")
allowed_mime_types = ["application/pdf", "image/jpeg", "image/png", "image/tiff"]
if file.content_type not in allowed_mime_types:
raise HTTPException(
status_code=400,
detail=f"Unsupported file type: '{file.content_type}'. Supported: {', '.join(allowed_mime_types)}",
)
print(f"Received file: {file.filename}")
file_id = str(create_key())
try:
file_path, file_content = save_uploaded_file(file, UPLOAD_DOCS_DIR, file_id)
except Exception as e:
raise HTTPException(status_code=500, detail=f"파일 저장 실패: {str(e)}")
try:
document_result = await run_sync_in_threadpool(
google_docai.process_document_from_content,
project_id=DOCAI_PROJECT_ID,
location=DOCAI_LOCATION,
processor_id=processor_id,
file_content=file_content,
mime_type=file.content_type,
field_mask="text,entities",
)
if not document_result:
raise HTTPException(status_code=500, detail="Document AI 처리 결과 없음.")
json_output_string = google_docai.extract_and_convert_to_json(document_result)
return json.loads(json_output_string)
except HTTPException as http_exc:
raise http_exc
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Document AI 처리 중 오류 발생: {str(e)}",
)
finally:
await file.close()
# app에 라우터 등록
app.include_router(doc_ai_router)
@app.get("/health/API")
async def health_check():
"""애플리케이션 상태 확인"""
return {"status": "API ok"}