63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
|
|
from fastapi.responses import StreamingResponse, JSONResponse
|
|
from core.renderer import ExcelRenderer
|
|
import io
|
|
import logging
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
app = FastAPI(
|
|
title="Excel2Pic API",
|
|
description="A lightweight service to convert Excel sheets to images.",
|
|
version="0.1.0"
|
|
)
|
|
|
|
@app.post("/api/v1/convert", summary="Convert Excel to Image")
|
|
async def convert_excel(
|
|
file: UploadFile = File(..., description="The Excel file to convert"),
|
|
sheet_name: str = Form(None, description="Name of the sheet to convert (optional, defaults to active sheet)"),
|
|
):
|
|
"""
|
|
Convert an uploaded Excel file to a PNG image.
|
|
"""
|
|
# Validation
|
|
if not file.filename.endswith(('.xlsx', '.xls')):
|
|
raise HTTPException(status_code=400, detail="Invalid file format. Please upload .xlsx or .xls file.")
|
|
|
|
try:
|
|
# Read file content
|
|
contents = await file.read()
|
|
|
|
# Initialize Renderer
|
|
# Note: In a real deployment, font paths might come from env vars
|
|
renderer = ExcelRenderer(contents)
|
|
|
|
# Render
|
|
image_bytes = renderer.render_to_bytes(sheet_name=sheet_name)
|
|
|
|
# Return as streaming response
|
|
# Handle Chinese filenames in Content-Disposition
|
|
from urllib.parse import quote
|
|
filename = file.filename.split('.')[0] + ".png"
|
|
encoded_filename = quote(filename)
|
|
|
|
return StreamingResponse(
|
|
io.BytesIO(image_bytes),
|
|
media_type="image/png",
|
|
headers={"Content-Disposition": f"inline; filename*=utf-8''{encoded_filename}"}
|
|
)
|
|
|
|
except ValueError as ve:
|
|
# Often raised when sheet name is not found
|
|
logger.warning(f"Value Error: {str(ve)}")
|
|
raise HTTPException(status_code=400, detail=str(ve))
|
|
except Exception as e:
|
|
logger.error(f"Internal Server Error: {str(e)}", exc_info=True)
|
|
raise HTTPException(status_code=500, detail=f"An error occurred during conversion: {str(e)}")
|
|
|
|
@app.get("/health", summary="Health Check")
|
|
def health_check():
|
|
return {"status": "ok"}
|