|
|
@@ -205,6 +205,7 @@ def get_version_files(version_id: str, flat: bool = False, db: Session = Depends
|
|
|
|
|
|
# ==================== File APIs ====================
|
|
|
|
|
|
+import urllib.parse
|
|
|
from fastapi.responses import RedirectResponse # noqa: E811
|
|
|
from app.services.oss_client import oss_client
|
|
|
|
|
|
@@ -230,13 +231,24 @@ def get_file_url(file_id: int, db: Session = Depends(get_db)):
|
|
|
|
|
|
@app.get("/files/{file_id}/content")
|
|
|
def get_file_content(file_id: int, db: Session = Depends(get_db)):
|
|
|
- """Redirect to CDN URL for file download."""
|
|
|
+ """Redirect to CDN URL for file download with forced attachment header."""
|
|
|
file_record = db.query(DataFile).filter(DataFile.id == file_id).first()
|
|
|
if not file_record:
|
|
|
raise HTTPException(status_code=404, detail="File not found")
|
|
|
|
|
|
cdn_url = oss_client.get_cdn_url(file_record.storage_path)
|
|
|
- return RedirectResponse(url=cdn_url)
|
|
|
+
|
|
|
+ # Try to force download by adding Aliyun OSS specific query parameter
|
|
|
+ # This works for Aliyun OSS even on custom domains if not explicitly disabled
|
|
|
+ filename = os.path.basename(file_record.relative_path)
|
|
|
+ quoted_filename = urllib.parse.quote(filename)
|
|
|
+ # Using both filename and filename* for maximum compatibility
|
|
|
+ disposition = f"attachment; filename=\"{quoted_filename}\"; filename*=UTF-8''{quoted_filename}"
|
|
|
+
|
|
|
+ separator = "&" if "?" in cdn_url else "?"
|
|
|
+ download_url = f"{cdn_url}{separator}response-content-disposition={urllib.parse.quote(disposition)}"
|
|
|
+
|
|
|
+ return RedirectResponse(url=download_url)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
import uvicorn
|