117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
# Copyright (c) 2025 Patrick Motsch
|
|
# All rights reserved.
|
|
|
|
"""
|
|
Download File By Path action for SharePoint operations.
|
|
Downloads file from SharePoint by exact file path.
|
|
"""
|
|
|
|
import logging
|
|
import json
|
|
import base64
|
|
import os
|
|
from typing import Dict, Any
|
|
from modules.workflows.methods.methodBase import action
|
|
from modules.datamodels.datamodelChat import ActionResult, ActionDocument
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
@action
|
|
async def downloadFileByPath(self, parameters: Dict[str, Any]) -> ActionResult:
|
|
"""
|
|
Download file from SharePoint by exact file path.
|
|
|
|
Parameters:
|
|
- connectionReference (str, required): Microsoft connection label.
|
|
- siteId (str, required): SharePoint site ID (from findSiteByUrl result) or document reference containing site info
|
|
- filePath (str, required): Full file path relative to site root (e.g., "/General/50 Docs hosted by SELISE/file.xlsx")
|
|
|
|
Returns:
|
|
- ActionResult with ActionDocument containing file content as base64-encoded bytes
|
|
"""
|
|
try:
|
|
connectionReference = parameters.get("connectionReference")
|
|
if not connectionReference:
|
|
return ActionResult.isFailure(error="connectionReference parameter is required")
|
|
|
|
siteIdParam = parameters.get("siteId")
|
|
if not siteIdParam:
|
|
return ActionResult.isFailure(error="siteId parameter is required")
|
|
|
|
filePath = parameters.get("filePath")
|
|
if not filePath:
|
|
return ActionResult.isFailure(error="filePath parameter is required")
|
|
|
|
# Extract siteId from document if it's a reference
|
|
siteId = None
|
|
if isinstance(siteIdParam, str):
|
|
# Try to parse from document reference
|
|
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:
|
|
pass
|
|
|
|
if not siteId:
|
|
# Assume it's the site ID directly
|
|
siteId = siteIdParam
|
|
else:
|
|
siteId = siteIdParam
|
|
|
|
if not siteId:
|
|
return ActionResult.isFailure(error="Could not extract siteId from parameter")
|
|
|
|
# Get Microsoft connection
|
|
connection = self.connection.getMicrosoftConnection(connectionReference)
|
|
if not connection:
|
|
return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
|
|
|
|
# Download file
|
|
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"
|
|
)
|
|
|
|
# Encode as base64
|
|
fileBase64 = base64.b64encode(fileContent).decode('utf-8')
|
|
|
|
validationMetadata = self._createValidationMetadata(
|
|
"downloadFileByPath",
|
|
siteId=siteId,
|
|
filePath=filePath,
|
|
fileSize=len(fileContent)
|
|
)
|
|
|
|
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)
|
|
|