main.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import os
  2. import subprocess
  3. import shutil
  4. from typing import Optional
  5. from fastapi import FastAPI, UploadFile, HTTPException
  6. from fastapi.responses import JSONResponse, FileResponse
  7. from fastapi.staticfiles import StaticFiles
  8. from fastapi.middleware.cors import CORSMiddleware
  9. from obs import ObsClient
  10. from dotenv import load_dotenv
  11. # Load environment variables
  12. load_dotenv()
  13. app = FastAPI()
  14. # Configure CORS
  15. app.add_middleware(
  16. CORSMiddleware,
  17. allow_origins=["*"], # Allows all origins
  18. allow_credentials=True,
  19. allow_methods=["*"], # Allows all methods
  20. allow_headers=["*"], # Allows all headers
  21. )
  22. # Mount static files
  23. app.mount("/static", StaticFiles(directory="static"), name="static")
  24. # OBS configuration
  25. ACCESS_KEY = os.getenv('OBS_ACCESS_KEY')
  26. SECRET_KEY = os.getenv('OBS_SECRET_KEY')
  27. ENDPOINT = os.getenv('OBS_ENDPOINT')
  28. BUCKET = os.getenv('OBS_BUCKET')
  29. # File paths
  30. UPLOAD_DIR = "/app/uploads"
  31. PROCESSED_DIR = "/app/processed"
  32. # Ensure directories exist
  33. os.makedirs(UPLOAD_DIR, exist_ok=True)
  34. os.makedirs(PROCESSED_DIR, exist_ok=True)
  35. def get_obs_client() -> ObsClient:
  36. return ObsClient(
  37. access_key_id=ACCESS_KEY,
  38. secret_access_key=SECRET_KEY,
  39. server=ENDPOINT
  40. )
  41. @app.get("/")
  42. async def root():
  43. return FileResponse("static/index.html")
  44. @app.post("/convert")
  45. async def convert_eps_to_svg(file: UploadFile):
  46. # Check file size (10MB limit)
  47. file_size = 0
  48. content = await file.read()
  49. file_size = len(content)
  50. if file_size > 10 * 1024 * 1024: # 10MB
  51. raise HTTPException(status_code=400, detail="File too large. Maximum size is 10MB")
  52. # Check file extension
  53. if not file.filename.lower().endswith('.eps'):
  54. raise HTTPException(status_code=400, detail="Only EPS files are accepted")
  55. try:
  56. # Ensure directories exist and are writable
  57. for directory in [UPLOAD_DIR, PROCESSED_DIR]:
  58. if not os.path.exists(directory):
  59. os.makedirs(directory, exist_ok=True)
  60. if not os.access(directory, os.W_OK):
  61. raise HTTPException(status_code=500, detail=f"Directory {directory} is not writable")
  62. # Save uploaded file
  63. input_path = os.path.join(UPLOAD_DIR, file.filename)
  64. with open(input_path, "wb") as f:
  65. f.write(content)
  66. # Generate output paths
  67. base_name = os.path.splitext(file.filename)[0]
  68. temp_svg = os.path.join(PROCESSED_DIR, f"{base_name}_temp.svg")
  69. final_svg = os.path.join(PROCESSED_DIR, f"{base_name}.svg")
  70. # Convert EPS to SVG
  71. try:
  72. subprocess.run(['eps2svg', input_path, temp_svg], check=True, capture_output=True, text=True)
  73. except subprocess.CalledProcessError as e:
  74. raise HTTPException(status_code=500, detail=f"eps2svg conversion failed: {e.stderr}")
  75. # Check if temp_svg was created
  76. if not os.path.exists(temp_svg):
  77. raise HTTPException(status_code=500, detail="eps2svg failed to create output file")
  78. # Try to optimize SVG using scour
  79. try:
  80. subprocess.run(['scour', '-i', temp_svg, '-o', final_svg], check=True)
  81. except subprocess.CalledProcessError:
  82. # If scour fails, use the unoptimized SVG
  83. shutil.copy(temp_svg, final_svg)
  84. print("Scour optimization failed, using unoptimized SVG")
  85. # Upload to OBS
  86. obs_client = get_obs_client()
  87. obs_key = f"svg/{base_name}.svg"
  88. with open(final_svg, 'rb') as f:
  89. obs_client.putContent(BUCKET, obs_key, f.read())
  90. # Clean up files
  91. os.remove(input_path)
  92. os.remove(temp_svg)
  93. os.remove(final_svg)
  94. return JSONResponse({
  95. "status": "success",
  96. "message": "File processed successfully",
  97. "obs_key": obs_key
  98. })
  99. except subprocess.CalledProcessError as e:
  100. raise HTTPException(status_code=500, detail=f"Error processing file: {str(e)}")
  101. except Exception as e:
  102. raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")
  103. @app.get("/health")
  104. def health_check():
  105. return {"status": "healthy"}