mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-26 17:26:23 +02:00
63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
"""Routes for exporting knowledge base content as ZIP."""
|
|
|
|
import logging
|
|
import os
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from fastapi.responses import StreamingResponse
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.db import Permission, User, get_async_session
|
|
from app.services.export_service import build_export_zip
|
|
from app.users import current_active_user
|
|
from app.utils.rbac import check_permission
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/search-spaces/{search_space_id}/export")
|
|
async def export_knowledge_base(
|
|
search_space_id: int,
|
|
folder_id: int | None = Query(
|
|
None, description="Export only this folder's subtree"
|
|
),
|
|
session: AsyncSession = Depends(get_async_session),
|
|
user: User = Depends(current_active_user),
|
|
):
|
|
"""Export documents as a ZIP of markdown files preserving folder structure."""
|
|
await check_permission(
|
|
session,
|
|
user,
|
|
search_space_id,
|
|
Permission.DOCUMENTS_READ.value,
|
|
"You don't have permission to export documents in this search space",
|
|
)
|
|
|
|
try:
|
|
result = await build_export_zip(session, search_space_id, folder_id)
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=404, detail=str(e)) from None
|
|
|
|
def stream_and_cleanup():
|
|
try:
|
|
with open(result.zip_path, "rb") as f:
|
|
while chunk := f.read(8192):
|
|
yield chunk
|
|
finally:
|
|
os.unlink(result.zip_path)
|
|
|
|
headers = {
|
|
"Content-Disposition": f'attachment; filename="{result.export_name}.zip"',
|
|
"Content-Length": str(result.zip_size),
|
|
}
|
|
|
|
if result.skipped_docs:
|
|
headers["X-Skipped-Documents"] = str(len(result.skipped_docs))
|
|
|
|
return StreamingResponse(
|
|
stream_and_cleanup(),
|
|
media_type="application/zip",
|
|
headers=headers,
|
|
)
|