diff --git a/README.md b/README.md index fecce1e..aed6540 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ This Python library is designed for testing the OData API of Creatio. It include - [Get Data from a Collection](#get-data-from-a-collection) - [Delete a Record from a Collection](#delete-a-record-from-a-collection) - [Handle information from the API session](#handle-information-from-the-api-session) + - [Download a file from a Collection's attachments](#download-a-file-from-a-collections-attachments) - [Contributors](#contributors) - [How do I contribute to creatio-api-py?](#how-do-i-contribute-to-creatio-api-py) - [License](#license) @@ -335,6 +336,23 @@ Additionally, you can modify the object's base url if needed: api.base_url = "https://another-environment.creatio.com" ``` +## Download a file from a Collection's attachments + +```python +file_id = "9dc61894-a14c-dff5-b4ff-6bca9a26018d" +api.download_file("ContactFile", file_id=file_id) +``` + +- Response code: `200 OK` +- Response body: The file content + +Additionally, you can specify the path where the file will be saved: + +```python +file_id = "9dc61894-a14c-dff5-b4ff-6bca9a26018d" +api.download_file("ContactFile", file_id=file_id, path="path/to/save/file") +``` + # Contributors diff --git a/creatio_api_py/api.py b/creatio_api_py/api.py index c47634a..aff621f 100644 --- a/creatio_api_py/api.py +++ b/creatio_api_py/api.py @@ -166,6 +166,7 @@ def _make_request( self, method: str, endpoint: str, + headers: Optional[dict[str, str]] = None, **kwargs: Any, ) -> requests.models.Response: """ @@ -180,7 +181,9 @@ def _make_request( requests.models.Response: The response from the HTTP request. """ url: str = f"{self.base_url}{endpoint}" - headers: dict[str, str] = self._build_headers(endpoint, method) + if not headers: + headers = {} + headers.update(self._build_headers(endpoint, method)) try: response: requests.Response = self.__session.request( @@ -457,3 +460,70 @@ def download_file( f.write(response.content) return response + + def upload_file( + self, collection: str, entity_id: str, file_path: str | Path + ) -> requests.models.Response: + """ + Upload a file to Creatio. + + Args: + collection (str): The collection to upload the file to. + entity_id (str): The ID of the entity to associate the file with. + file_path (str | Path): The path to the file to upload. + + Returns: + requests.models.Response: The response from the file upload request. + """ + # Read the file data to ensure the file is valid + file_path = file_path if isinstance(file_path, Path) else Path(file_path) + with open(file_path, "rb") as f: + data: bytes = f.read() + + file_length: int = len(data) + parent_collection: str = collection[: -len("File")] + + # Create the file in the collection table + payload: dict[str, Any] = { + "Name": file_path.name, + f"{parent_collection}Id": entity_id, + "Size": file_length, + "TotalSize": file_length, + "TypeId": "529bc2f8-0ee0-df11-971b-001d60e938c6", + } + response: requests.Response = self.add_collection_data(collection, data=payload) + response.raise_for_status() + + # Get the file ID from the response + file_id: str = response.json().get("Id") + if not file_id: + raise ValueError("Could not determine the file ID from the response") + + content_type = "application/pdf" + params: dict[str, str | int] = { + "fileId": file_id, + "totalFileLength": file_length, + #"mimeType": content_type, + "fileName": file_path.name, + "columnName": "Data", + "entitySchemaName": collection, + "parentColumnName": parent_collection, + "parentColumnValue": entity_id, + } + + headers: dict[str, str] = { + "Content-Type": content_type, + "Content-Disposition": f"attachment; filename={file_path.name}", + } + + # TODO: Fix this call, currently returns a InvalidFileSizeException error + # Probably related to content-type header and mimeType value + response = self._make_request( + "POST", + f"0/rest/FileApiService/UploadFile", + params=params, + data=data, + ) + response.raise_for_status() + + return response diff --git a/pyproject.toml b/pyproject.toml index 5c1dc4b..b40b5be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "creatio-api-py" -version = "1.3.0" +version = "1.3.1" description = "Python client for Creatio OData API" authors = [ { name = "Alejandro González Momblán", email = "alejandro.gonzalez.momblan@evoluciona.es" },