Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, File, UploadFile, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| import pdfplumber | |
| from io import BytesIO | |
| import base64 | |
| import uvicorn | |
| import logging | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| app = FastAPI() | |
| # Add CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Root route | |
| async def root(): | |
| return {"message": "PDF to Figma API"} | |
| async def convert_pdf(file: UploadFile = File(...)): | |
| try: | |
| logger.info("Received file: %s", file.filename) | |
| # Read the uploaded file | |
| contents = await file.read() | |
| if not contents: | |
| logger.error("Empty file uploaded") | |
| raise HTTPException(status_code=400, detail="Empty file uploaded") | |
| # Parse PDF with pdfplumber | |
| with pdfplumber.open(BytesIO(contents)) as pdf: | |
| if not pdf.pages: | |
| logger.error("No pages found in PDF") | |
| raise HTTPException(status_code=400, detail="No pages found in PDF") | |
| page = pdf.pages[0] # First page | |
| width, height = page.width, page.height | |
| logger.info("Processing PDF page: width=%s, height=%s", width, height) | |
| # Initialize result | |
| result = { | |
| "width": width, | |
| "height": height, | |
| "texts": [], | |
| "images": [], | |
| "shapes": [] | |
| } | |
| # Extract text | |
| for char in page.chars: | |
| result["texts"].append({ | |
| "content": char["text"], | |
| "x": char["x0"], | |
| "y": char["y0"], | |
| "font_family": char["fontname"].split("+")[-1] or "Arial", | |
| "font_style": "Regular", | |
| "font_size": char["size"], | |
| "color": {"r": 0, "g": 0, "b": 0} | |
| }) | |
| # Extract images | |
| for img in page.images: | |
| try: | |
| img_data = img["stream"].get_data() | |
| result["images"].append({ | |
| "data": list(img_data), | |
| "x": img["x0"], | |
| "y": img["y0"], | |
| "width": img["width"], | |
| "height": img["height"] | |
| }) | |
| except Exception as e: | |
| logger.warning("Failed to extract image: %s", str(e)) | |
| continue | |
| # Extract shapes | |
| for curve in page.curves: | |
| try: | |
| path = " ".join([f"M {p['x']},{p['y']}" for p in curve["points"]]) | |
| result["shapes"].append({ | |
| "path": path, | |
| "x": curve["x0"], | |
| "y": curve["y0"], | |
| "color": {"r": 0, "g": 0, "b": 0} | |
| }) | |
| except Exception as e: | |
| logger.warning("Failed to extract shape: %s", str(e)) | |
| continue | |
| logger.info("PDF processing complete") | |
| return JSONResponse(content=result) | |
| except Exception as e: | |
| logger.error("Failed to process PDF: %s", str(e)) | |
| raise HTTPException(status_code=500, detail=f"Failed to process PDF: {str(e)}") | |
| finally: | |
| await file.close() | |
| # Run uvicorn server | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |