Pushkar Pandey
fix: move backend files to root for HuggingFace
61ec498
Raw
History Blame Contribute Delete
2.79 kB
# backend/app/api/upload.py
from fastapi import APIRouter, UploadFile, File, HTTPException, Depends
import os
import tempfile
import csv
import io
from app.models.schemas import Transaction, UploadResponse
from app.ai.extraction_agent import extract_text_from_pdf, parse_text_to_json, extract_all_transaction
from app.api.rate_limiter import upload_rate_limiter
router = APIRouter()
@router.post("/", response_model=UploadResponse, dependencies=[Depends(upload_rate_limiter)])
async def upload_document(file: UploadFile = File(...)):
"""Receives a CSV file, performs security validation, and parses it into structured data."""
transactions = []
try:
# --- SECURITY VERIFICATION ---
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB
# 1. Validate Extension & MIME Type to prevent malicious scripts
if not file.filename.lower().endswith('.csv') or file.content_type not in ["text/csv", "application/vnd.ms-excel"]:
raise HTTPException(status_code=400, detail="Security Error: Only valid CSV files are allowed.")
contents = await file.read()
# 2. Prevent massive files from crashing memory
if len(contents) > MAX_FILE_SIZE:
raise HTTPException(status_code=413, detail="File too large. Maximum size is 5MB.")
# --- PATH 1: The CSV Fast-Track ---
print(f"✅ Fast-Track triggered for CSV: {file.filename}")
# Use utf-8-sig to handle Excel BOM characters automatically!
decoded_contents = contents.decode('utf-8-sig')
reader = csv.DictReader(io.StringIO(decoded_contents))
print(f"🔍 CSV Headers detected: {reader.fieldnames}")
for row in reader:
# Convert all keys in the row to lowercase and strip whitespace
lower_row = {k.lower().strip() if k else '': str(v).strip() for k, v in row.items()}
raw_amount = lower_row.get('amount', '0').replace('$', '').replace(',', '')
txn = Transaction(
date=lower_row.get('date', ''),
description=lower_row.get('description', ''),
amount=float(raw_amount) if raw_amount else 0.0
)
transactions.append(txn)
print(f"🎯 Total transactions parsed from CSV: {len(transactions)}")
# (PDF Parsing hidden for MVP)
return {
"message": "Upload & Extraction successful",
"transaction_count": len(transactions),
"preview": transactions[:3],
"transactions": transactions
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error processing file: {str(e)}")