# 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)