123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import os
- import subprocess
- import shutil
- from typing import Optional
- from fastapi import FastAPI, UploadFile, HTTPException
- from fastapi.responses import JSONResponse, FileResponse
- from fastapi.staticfiles import StaticFiles
- from fastapi.middleware.cors import CORSMiddleware
- from obs import ObsClient
- from dotenv import load_dotenv
- # Load environment variables
- load_dotenv()
- app = FastAPI()
- # Configure CORS
- app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"], # Allows all origins
- allow_credentials=True,
- allow_methods=["*"], # Allows all methods
- allow_headers=["*"], # Allows all headers
- )
- # Mount static files
- app.mount("/static", StaticFiles(directory="static"), name="static")
- # OBS configuration
- ACCESS_KEY = os.getenv('OBS_ACCESS_KEY')
- SECRET_KEY = os.getenv('OBS_SECRET_KEY')
- ENDPOINT = os.getenv('OBS_ENDPOINT')
- BUCKET = os.getenv('OBS_BUCKET')
- # File paths
- UPLOAD_DIR = "/app/uploads"
- PROCESSED_DIR = "/app/processed"
- # Ensure directories exist
- os.makedirs(UPLOAD_DIR, exist_ok=True)
- os.makedirs(PROCESSED_DIR, exist_ok=True)
- def get_obs_client() -> ObsClient:
- return ObsClient(
- access_key_id=ACCESS_KEY,
- secret_access_key=SECRET_KEY,
- server=ENDPOINT
- )
- @app.get("/")
- async def root():
- return FileResponse("static/index.html")
- @app.post("/convert")
- async def convert_eps_to_svg(file: UploadFile):
- # Check file size (10MB limit)
- file_size = 0
- content = await file.read()
- file_size = len(content)
- if file_size > 10 * 1024 * 1024: # 10MB
- raise HTTPException(status_code=400, detail="File too large. Maximum size is 10MB")
-
- # Check file extension
- if not file.filename.lower().endswith('.eps'):
- raise HTTPException(status_code=400, detail="Only EPS files are accepted")
-
- try:
- # Ensure directories exist and are writable
- for directory in [UPLOAD_DIR, PROCESSED_DIR]:
- if not os.path.exists(directory):
- os.makedirs(directory, exist_ok=True)
- if not os.access(directory, os.W_OK):
- raise HTTPException(status_code=500, detail=f"Directory {directory} is not writable")
- # Save uploaded file
- input_path = os.path.join(UPLOAD_DIR, file.filename)
- with open(input_path, "wb") as f:
- f.write(content)
-
- # Generate output paths
- base_name = os.path.splitext(file.filename)[0]
- temp_svg = os.path.join(PROCESSED_DIR, f"{base_name}_temp.svg")
- final_svg = os.path.join(PROCESSED_DIR, f"{base_name}.svg")
-
- # Convert EPS to SVG
- try:
- subprocess.run(['eps2svg', input_path, temp_svg], check=True, capture_output=True, text=True)
- except subprocess.CalledProcessError as e:
- raise HTTPException(status_code=500, detail=f"eps2svg conversion failed: {e.stderr}")
-
- # Check if temp_svg was created
- if not os.path.exists(temp_svg):
- raise HTTPException(status_code=500, detail="eps2svg failed to create output file")
-
- # Try to optimize SVG using scour
- try:
- subprocess.run(['scour', '-i', temp_svg, '-o', final_svg], check=True)
- except subprocess.CalledProcessError:
- # If scour fails, use the unoptimized SVG
- shutil.copy(temp_svg, final_svg)
- print("Scour optimization failed, using unoptimized SVG")
-
- # Upload to OBS
- obs_client = get_obs_client()
- obs_key = f"svg/{base_name}.svg"
-
- with open(final_svg, 'rb') as f:
- obs_client.putContent(BUCKET, obs_key, f.read())
-
- # Clean up files
- os.remove(input_path)
- os.remove(temp_svg)
- os.remove(final_svg)
-
- return JSONResponse({
- "status": "success",
- "message": "File processed successfully",
- "obs_key": obs_key
- })
-
- except subprocess.CalledProcessError as e:
- raise HTTPException(status_code=500, detail=f"Error processing file: {str(e)}")
- except Exception as e:
- raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")
- @app.get("/health")
- def health_check():
- return {"status": "healthy"}
|