gateway/modules/workflows/methods/methodSharepoint/actions/downloadFileByPath.py
2026-03-22 19:46:50 +01:00

129 lines
6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
import logging
import json
import base64
import os
from typing import Dict, Any
from modules.datamodels.datamodelChat import ActionResult, ActionDocument
logger = logging.getLogger(__name__)
async def downloadFileByPath(self, parameters: Dict[str, Any]) -> ActionResult:
try:
connectionReference = parameters.get("connectionReference")
if not connectionReference:
return ActionResult.isFailure(error="connectionReference parameter is required")
# Set SharePoint access token first required before siteDiscovery/sharepoint calls
connection = self.connection.getMicrosoftConnection(connectionReference)
if not connection:
return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
pathQuery = (parameters.get("pathQuery") or parameters.get("path") or "").strip()
siteIdParam = parameters.get("siteId")
filePath = parameters.get("filePath")
# If filePath looks like full SharePoint path, use as pathQuery fallback
if not pathQuery and filePath and isinstance(filePath, str) and filePath.strip().startswith("/sites/"):
pathQuery = filePath.strip()
siteId = None
innerPath = None
# Option 1: pathQuery provided (e.g. /sites/SiteName/Shared Documents/file.pdf) resolve site and inner path
if pathQuery and pathQuery != "*":
sites, errorMsg = await self.siteDiscovery.resolveSitesFromPathQuery(pathQuery)
if errorMsg:
return ActionResult.isFailure(error=errorMsg)
if not sites:
return ActionResult.isFailure(error="Could not resolve site from pathQuery")
parsedPath = self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
if not parsedPath:
return ActionResult.isFailure(error="pathQuery must be a standard SharePoint path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
innerPath = (parsedPath.get("innerPath") or "").strip()
if not innerPath:
return ActionResult.isFailure(error="pathQuery must include a file path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
siteId = sites[0].get("id")
filePath = innerPath
elif siteIdParam and filePath:
# Option 2: siteId + filePath provided directly
if isinstance(siteIdParam, str):
from modules.datamodels.datamodelDocref import DocumentReferenceList
try:
docList = DocumentReferenceList.from_string_list([siteIdParam])
chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList)
if chatDocuments and len(chatDocuments) > 0:
siteInfoJson = json.loads(chatDocuments[0].documentData)
siteId = siteInfoJson.get("id")
except Exception:
pass
if not siteId:
siteId = siteIdParam
else:
siteId = siteIdParam
else:
return ActionResult.isFailure(error="Either pathQuery (e.g. /sites/SiteName/Shared Documents/file.pdf) or both siteId and filePath are required")
if not siteId or not filePath:
return ActionResult.isFailure(error="Could not resolve siteId and file path from parameters")
# Download file (connection/token already set above)
fileContent = await self.services.sharepoint.downloadFileByPath(
siteId=siteId,
filePath=filePath
)
if fileContent is None:
return ActionResult.isFailure(error=f"File not found or could not be downloaded: {filePath}")
logger.info(f"Downloaded file from SharePoint: {filePath} ({len(fileContent)} bytes)")
# Generate filename from filePath
fileName = os.path.basename(filePath) or "downloaded_file"
workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None
filename = self._generateMeaningfulFileName(
fileName.split('.')[0] if '.' in fileName else fileName,
fileName.split('.')[-1] if '.' in fileName else "bin",
workflowContext,
"downloadFileByPath"
)
# Save to user's Files (FileItem + FileData) via interfaceDbComponent appears in Files UI
fileItem = None
db = getattr(self.services, "interfaceDbComponent", None)
if db:
try:
mimeType = db.getMimeType(filename) if hasattr(db, "getMimeType") else "application/octet-stream"
fileItem = db.createFile(name=filename, mimeType=mimeType, content=fileContent)
db.createFileData(fileItem.id, fileContent)
logger.info(f"Saved SharePoint file to user Files: {filename} (id={fileItem.id})")
except Exception as e:
logger.warning(f"Could not save to user Files: {e}")
# Encode as base64 for workflow context (AI, data nodes)
fileBase64 = base64.b64encode(fileContent).decode('utf-8')
validationMetadata = self._createValidationMetadata(
"downloadFileByPath",
siteId=siteId,
filePath=filePath,
fileSize=len(fileContent)
)
if fileItem:
validationMetadata["fileId"] = fileItem.id
document = ActionDocument(
documentName=filename,
documentData=fileBase64,
mimeType="application/octet-stream",
validationMetadata=validationMetadata
)
return ActionResult.isSuccess(documents=[document])
except Exception as e:
errorMsg = f"Error downloading file from SharePoint: {str(e)}"
logger.error(errorMsg)
return ActionResult.isFailure(error=errorMsg)