Update backend/app/main.py

#1
by raahinaez - opened
Files changed (1) hide show
  1. 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 unique filename on disk
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 = Path(row[2])
872
- if file_path.exists():
873
- return FileResponse(
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 not db_asset:
890
- raise HTTPException(status_code=404, detail="Asset not found")
 
 
891
 
892
- file_path = Path(db_asset.file_path)
 
 
 
893
  if not file_path.exists():
894
- raise HTTPException(status_code=404, detail="File not found on disk")
 
 
 
895
 
896
  # Determine media type
897
- media_type = "application/octet-stream"
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=db_asset.name,
921
- media_type=media_type
 
 
 
922
  )
923
  except HTTPException:
924
  raise
925
  except Exception as e:
926
- raise HTTPException(status_code=500, detail=str(e))
 
 
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