Spaces:
Sleeping
Sleeping
Update backend/app/main.py
#1
by
raahinaez
- opened
- backend/app/main.py +81 -43
backend/app/main.py
CHANGED
|
@@ -430,6 +430,8 @@ async def upload_asset(
|
|
| 430 |
file_suffix = Path(safe_filename).suffix
|
| 431 |
unique_filename = f"{file_stem}_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}{file_suffix}"
|
| 432 |
file_path = upload_dir / unique_filename
|
|
|
|
|
|
|
| 433 |
with open(file_path, "wb") as buffer:
|
| 434 |
buffer.write(content)
|
| 435 |
|
|
@@ -441,7 +443,7 @@ async def upload_asset(
|
|
| 441 |
|
| 442 |
db_asset = Asset(
|
| 443 |
name=file.filename, # Keep original filename for display
|
| 444 |
-
file_path=str(file_path), # Store
|
| 445 |
file_type=file_type,
|
| 446 |
product_category=product_category or "ocr",
|
| 447 |
sub_category=sub_category if sub_category and sub_category != "none" else None,
|
|
@@ -466,7 +468,7 @@ async def upload_asset(
|
|
| 466 |
SELECT id, created_at FROM assets
|
| 467 |
WHERE name = %s AND file_path = %s
|
| 468 |
ORDER BY id DESC LIMIT 1
|
| 469 |
-
""", (file.filename, str(file_path)))
|
| 470 |
row = cursor.fetchone()
|
| 471 |
cursor.close()
|
| 472 |
conn.close()
|
|
@@ -500,7 +502,7 @@ async def upload_asset(
|
|
| 500 |
RETURNING id, created_at
|
| 501 |
""", (
|
| 502 |
file.filename,
|
| 503 |
-
str(file_path),
|
| 504 |
file_type,
|
| 505 |
product_category or "ocr",
|
| 506 |
sub_category if sub_category and sub_category != "none" else None,
|
|
@@ -837,6 +839,47 @@ async def get_pdf_pages(asset_id, db: Session = Depends(get_db)):
|
|
| 837 |
except Exception as e:
|
| 838 |
raise HTTPException(status_code=500, detail=str(e))
|
| 839 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 840 |
@app.get("/api/assets/{asset_id}/download")
|
| 841 |
async def download_asset(asset_id, db: Session = Depends(get_db)):
|
| 842 |
"""Download or preview an asset file"""
|
|
@@ -850,6 +893,11 @@ async def download_asset(asset_id, db: Session = Depends(get_db)):
|
|
| 850 |
raise HTTPException(status_code=400, detail=f"Invalid asset ID: {asset_id}")
|
| 851 |
|
| 852 |
# Try to get asset from database
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 853 |
try:
|
| 854 |
db_asset = db.query(Asset).filter(Asset.id == asset_id_int).first()
|
| 855 |
except Exception as orm_error:
|
|
@@ -868,62 +916,52 @@ async def download_asset(asset_id, db: Session = Depends(get_db)):
|
|
| 868 |
cursor.close()
|
| 869 |
conn.close()
|
| 870 |
if row:
|
| 871 |
-
file_path =
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
path=str(file_path),
|
| 875 |
-
filename=row[1],
|
| 876 |
-
media_type="application/octet-stream"
|
| 877 |
-
)
|
| 878 |
-
else:
|
| 879 |
-
raise HTTPException(status_code=404, detail="File not found on disk")
|
| 880 |
else:
|
| 881 |
-
raise HTTPException(status_code=404, detail="Asset not found")
|
|
|
|
|
|
|
| 882 |
except Exception as psycopg2_error:
|
| 883 |
if conn:
|
| 884 |
conn.close()
|
| 885 |
-
raise HTTPException(status_code=500, detail=str(psycopg2_error))
|
| 886 |
else:
|
| 887 |
-
raise HTTPException(status_code=500, detail=str(orm_error))
|
| 888 |
|
| 889 |
-
if
|
| 890 |
-
|
|
|
|
|
|
|
| 891 |
|
| 892 |
-
|
|
|
|
|
|
|
|
|
|
| 893 |
if not file_path.exists():
|
| 894 |
-
raise HTTPException(
|
|
|
|
|
|
|
|
|
|
| 895 |
|
| 896 |
# Determine media type
|
| 897 |
-
media_type =
|
| 898 |
-
if db_asset.file_type == "image":
|
| 899 |
-
if file_path.suffix.lower() in [".jpg", ".jpeg"]:
|
| 900 |
-
media_type = "image/jpeg"
|
| 901 |
-
elif file_path.suffix.lower() == ".png":
|
| 902 |
-
media_type = "image/png"
|
| 903 |
-
elif file_path.suffix.lower() == ".gif":
|
| 904 |
-
media_type = "image/gif"
|
| 905 |
-
elif file_path.suffix.lower() == ".webp":
|
| 906 |
-
media_type = "image/webp"
|
| 907 |
-
elif db_asset.file_type == "video":
|
| 908 |
-
if file_path.suffix.lower() == ".mp4":
|
| 909 |
-
media_type = "video/mp4"
|
| 910 |
-
elif file_path.suffix.lower() == ".webm":
|
| 911 |
-
media_type = "video/webm"
|
| 912 |
-
elif db_asset.file_type == "document":
|
| 913 |
-
if file_path.suffix.lower() == ".pdf":
|
| 914 |
-
media_type = "application/pdf"
|
| 915 |
-
elif file_path.suffix.lower() in [".doc", ".docx"]:
|
| 916 |
-
media_type = "application/msword"
|
| 917 |
|
| 918 |
return FileResponse(
|
| 919 |
-
path=str(file_path),
|
| 920 |
-
filename=
|
| 921 |
-
media_type=media_type
|
|
|
|
|
|
|
|
|
|
| 922 |
)
|
| 923 |
except HTTPException:
|
| 924 |
raise
|
| 925 |
except Exception as e:
|
| 926 |
-
|
|
|
|
|
|
|
| 927 |
|
| 928 |
# ---- Post Management ----
|
| 929 |
|
|
|
|
| 430 |
file_suffix = Path(safe_filename).suffix
|
| 431 |
unique_filename = f"{file_stem}_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}{file_suffix}"
|
| 432 |
file_path = upload_dir / unique_filename
|
| 433 |
+
# Convert to absolute path before storing
|
| 434 |
+
file_path = file_path.resolve()
|
| 435 |
with open(file_path, "wb") as buffer:
|
| 436 |
buffer.write(content)
|
| 437 |
|
|
|
|
| 443 |
|
| 444 |
db_asset = Asset(
|
| 445 |
name=file.filename, # Keep original filename for display
|
| 446 |
+
file_path=str(file_path), # Store absolute path
|
| 447 |
file_type=file_type,
|
| 448 |
product_category=product_category or "ocr",
|
| 449 |
sub_category=sub_category if sub_category and sub_category != "none" else None,
|
|
|
|
| 468 |
SELECT id, created_at FROM assets
|
| 469 |
WHERE name = %s AND file_path = %s
|
| 470 |
ORDER BY id DESC LIMIT 1
|
| 471 |
+
""", (file.filename, str(file_path.resolve())))
|
| 472 |
row = cursor.fetchone()
|
| 473 |
cursor.close()
|
| 474 |
conn.close()
|
|
|
|
| 502 |
RETURNING id, created_at
|
| 503 |
""", (
|
| 504 |
file.filename,
|
| 505 |
+
str(file_path.resolve()), # Store absolute path
|
| 506 |
file_type,
|
| 507 |
product_category or "ocr",
|
| 508 |
sub_category if sub_category and sub_category != "none" else None,
|
|
|
|
| 839 |
except Exception as e:
|
| 840 |
raise HTTPException(status_code=500, detail=str(e))
|
| 841 |
|
| 842 |
+
def _get_media_type(file_path: Path, file_type: str) -> str:
|
| 843 |
+
"""Determine media type from file path and type"""
|
| 844 |
+
media_type = "application/octet-stream"
|
| 845 |
+
suffix = file_path.suffix.lower()
|
| 846 |
+
|
| 847 |
+
if file_type == "image" or suffix in [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"]:
|
| 848 |
+
if suffix in [".jpg", ".jpeg"]:
|
| 849 |
+
media_type = "image/jpeg"
|
| 850 |
+
elif suffix == ".png":
|
| 851 |
+
media_type = "image/png"
|
| 852 |
+
elif suffix == ".gif":
|
| 853 |
+
media_type = "image/gif"
|
| 854 |
+
elif suffix == ".webp":
|
| 855 |
+
media_type = "image/webp"
|
| 856 |
+
elif suffix == ".svg":
|
| 857 |
+
media_type = "image/svg+xml"
|
| 858 |
+
elif file_type == "video" or suffix in [".mp4", ".webm", ".mov", ".avi"]:
|
| 859 |
+
if suffix == ".mp4":
|
| 860 |
+
media_type = "video/mp4"
|
| 861 |
+
elif suffix == ".webm":
|
| 862 |
+
media_type = "video/webm"
|
| 863 |
+
elif suffix == ".mov":
|
| 864 |
+
media_type = "video/quicktime"
|
| 865 |
+
elif file_type == "document" or suffix in [".pdf", ".doc", ".docx"]:
|
| 866 |
+
if suffix == ".pdf":
|
| 867 |
+
media_type = "application/pdf"
|
| 868 |
+
elif suffix in [".doc", ".docx"]:
|
| 869 |
+
media_type = "application/msword"
|
| 870 |
+
return media_type
|
| 871 |
+
|
| 872 |
+
def _resolve_file_path(path_str: str) -> Path:
|
| 873 |
+
"""Resolve file path (handle both absolute and relative paths)"""
|
| 874 |
+
file_path = Path(path_str)
|
| 875 |
+
if not file_path.is_absolute():
|
| 876 |
+
# If relative, assume it's relative to uploads directory
|
| 877 |
+
upload_dir = Path("uploads")
|
| 878 |
+
file_path = (upload_dir / file_path).resolve()
|
| 879 |
+
else:
|
| 880 |
+
file_path = file_path.resolve()
|
| 881 |
+
return file_path
|
| 882 |
+
|
| 883 |
@app.get("/api/assets/{asset_id}/download")
|
| 884 |
async def download_asset(asset_id, db: Session = Depends(get_db)):
|
| 885 |
"""Download or preview an asset file"""
|
|
|
|
| 893 |
raise HTTPException(status_code=400, detail=f"Invalid asset ID: {asset_id}")
|
| 894 |
|
| 895 |
# Try to get asset from database
|
| 896 |
+
db_asset = None
|
| 897 |
+
file_path = None
|
| 898 |
+
file_name = None
|
| 899 |
+
file_type = None
|
| 900 |
+
|
| 901 |
try:
|
| 902 |
db_asset = db.query(Asset).filter(Asset.id == asset_id_int).first()
|
| 903 |
except Exception as orm_error:
|
|
|
|
| 916 |
cursor.close()
|
| 917 |
conn.close()
|
| 918 |
if row:
|
| 919 |
+
file_path = _resolve_file_path(row[2])
|
| 920 |
+
file_name = row[1]
|
| 921 |
+
file_type = row[3]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 922 |
else:
|
| 923 |
+
raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")
|
| 924 |
+
except HTTPException:
|
| 925 |
+
raise
|
| 926 |
except Exception as psycopg2_error:
|
| 927 |
if conn:
|
| 928 |
conn.close()
|
| 929 |
+
raise HTTPException(status_code=500, detail=f"Database error: {str(psycopg2_error)}")
|
| 930 |
else:
|
| 931 |
+
raise HTTPException(status_code=500, detail=f"ORM error: {str(orm_error)}")
|
| 932 |
|
| 933 |
+
if db_asset:
|
| 934 |
+
file_path = _resolve_file_path(db_asset.file_path)
|
| 935 |
+
file_name = db_asset.name
|
| 936 |
+
file_type = db_asset.file_type
|
| 937 |
|
| 938 |
+
if not file_path:
|
| 939 |
+
raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")
|
| 940 |
+
|
| 941 |
+
# Check if file exists
|
| 942 |
if not file_path.exists():
|
| 943 |
+
raise HTTPException(
|
| 944 |
+
status_code=404,
|
| 945 |
+
detail=f"File not found on disk. Expected path: {file_path.absolute()}"
|
| 946 |
+
)
|
| 947 |
|
| 948 |
# Determine media type
|
| 949 |
+
media_type = _get_media_type(file_path, file_type)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 950 |
|
| 951 |
return FileResponse(
|
| 952 |
+
path=str(file_path.absolute()),
|
| 953 |
+
filename=file_name,
|
| 954 |
+
media_type=media_type,
|
| 955 |
+
headers={
|
| 956 |
+
"Content-Disposition": f'inline; filename="{file_name}"' # Use 'inline' for preview
|
| 957 |
+
}
|
| 958 |
)
|
| 959 |
except HTTPException:
|
| 960 |
raise
|
| 961 |
except Exception as e:
|
| 962 |
+
import traceback
|
| 963 |
+
print(f"Download error for asset {asset_id}: {traceback.format_exc()}")
|
| 964 |
+
raise HTTPException(status_code=500, detail=f"Download failed: {str(e)}")
|
| 965 |
|
| 966 |
# ---- Post Management ----
|
| 967 |
|