feat folder download as zip
This commit is contained in:
parent
d63a41fbc8
commit
6296b79ad0
1 changed files with 66 additions and 0 deletions
|
|
@ -441,6 +441,72 @@ def move_folder(
|
|||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/folders/{folderId}/download")
|
||||
@limiter.limit("10/minute")
|
||||
def download_folder(
|
||||
request: Request,
|
||||
folderId: str = Path(..., description="ID of the folder to download as ZIP"),
|
||||
currentUser: User = Depends(getCurrentUser),
|
||||
context: RequestContext = Depends(getRequestContext)
|
||||
) -> Response:
|
||||
"""Download a folder (including subfolders) as a ZIP archive."""
|
||||
import io
|
||||
import zipfile
|
||||
import urllib.parse
|
||||
|
||||
try:
|
||||
mgmt = interfaceDbManagement.getInterface(
|
||||
currentUser,
|
||||
mandateId=str(context.mandateId) if context.mandateId else None,
|
||||
featureInstanceId=str(context.featureInstanceId) if context.featureInstanceId else None,
|
||||
)
|
||||
|
||||
folder = mgmt.getFolder(folderId)
|
||||
if not folder:
|
||||
raise HTTPException(status_code=404, detail=f"Folder {folderId} not found")
|
||||
|
||||
folderName = folder.get("name", "download")
|
||||
|
||||
def _collectFiles(parentId: str, pathPrefix: str):
|
||||
"""Recursively collect (zipPath, fileId) tuples."""
|
||||
entries = []
|
||||
for f in mgmt._getFilesByCurrentUser(recordFilter={"folderId": parentId}):
|
||||
fname = f.get("fileName") or f.get("name") or f.get("id", "file")
|
||||
entries.append((f"{pathPrefix}{fname}", f["id"]))
|
||||
for sub in mgmt.listFolders(parentId=parentId):
|
||||
subName = sub.get("name", sub["id"])
|
||||
entries.extend(_collectFiles(sub["id"], f"{pathPrefix}{subName}/"))
|
||||
return entries
|
||||
|
||||
fileEntries = _collectFiles(folderId, "")
|
||||
if not fileEntries:
|
||||
raise HTTPException(status_code=404, detail="Folder is empty")
|
||||
|
||||
buf = io.BytesIO()
|
||||
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||
for zipPath, fileId in fileEntries:
|
||||
data = mgmt.getFileData(fileId)
|
||||
if data:
|
||||
zf.writestr(zipPath, data)
|
||||
|
||||
buf.seek(0)
|
||||
zipBytes = buf.getvalue()
|
||||
encodedName = urllib.parse.quote(f"{folderName}.zip")
|
||||
|
||||
return Response(
|
||||
content=zipBytes,
|
||||
media_type="application/zip",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename*=UTF-8''{encodedName}"
|
||||
}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error downloading folder as ZIP: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Error downloading folder: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/batch-delete")
|
||||
@limiter.limit("10/minute")
|
||||
def batch_delete_items(
|
||||
|
|
|
|||
Loading…
Reference in a new issue