Download Files
Download file attachments and images from DealCloud. Downloads use GET .../entryfiles/{entryId}/fields/{fieldId}; the SDK does not take object_id for download_file() (see intapp-rest-client streaming downloads).
download_file()
Download a file's binary content. You can either get bytes in memory or stream directly to a file path (memory-efficient for large files).
from dealcloud_sdk import DealCloud, DealCloudConfig
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)
# Option 1: Get bytes in memory
content = dc.download_file(
entry_id=12345,
field_id=67890, # Binary field ID or API name
)
with open("document.pdf", "wb") as f:
f.write(content)
# Option 2: Save directly to file (streaming; use for large files)
path = dc.download_file(
entry_id=12345,
field_id=67890,
output_path="./document.pdf",
)
# Option 3: With progress callback
def on_progress(downloaded, total):
if total:
print(f"{100 * downloaded / total:.1f}%")
path = dc.download_file(
entry_id=12345,
field_id=67890,
output_path="./document.pdf",
progress_callback=on_progress,
)download_attachment() is an alias with the same signature.
Parameters
| Parameter | Type | Description |
|---|---|---|
entry_id | int | Entry ID containing the file |
field_id | str | int | Field ID or API name of the IMAGE or BINARY field |
output_path | str | None | Optional. If set, file is streamed to this path and the path is returned. |
progress_callback | Callable | None | Optional. Called with (bytes_downloaded, total_bytes). |
Returns
- If
output_pathisNone:bytes(raw file content). - If
output_pathis set:str(path to the saved file).
download_attachment_metadata()
Get file metadata without downloading content. This helper loads the row via the data query API and reads the field’s metadata (there is no separate entryfiles/.../info endpoint).
info = dc.download_attachment_metadata(
object_id="Attachment", # object that owns the row
entry_id=12345,
field_id=67890,
)
print(f"Filename: {info.get('fileName')}")
print(f"Size: {info.get('fileSize')} bytes")
print(f"Type: {info.get('contentType')}")Response Properties
| Property | Type | Description |
|---|---|---|
fileName | str | Original filename |
fileSize | int | None | File size in bytes (when present) |
contentType | str | MIME type |
uploadDate | str | None | Upload timestamp (when present) |
Downloading Images
For image fields (fieldType: 16):
# Download company logo (same entryfiles URL as documents)
logo = dc.download_file(
entry_id=12345,
field_id="Logo", # Image field
)
# Save with extension
with open("company_logo.png", "wb") as f:
f.write(logo)Downloading Attachments
For attachment references (fieldType: 5 → Attachments object):
# 1. Read the attachment reference
deal = dc.read_data(
"Deal",
output="list",
fields=["EntryId", "Contract"], # Contract is attachment reference
query="{EntryId: 12345}",
)[0]
# 2. Resolve attachment Entry ID
attachment_ref = deal.get("Contract")
if attachment_ref:
attachment_id = attachment_ref["id"] if isinstance(attachment_ref, dict) else attachment_ref
# 3. Download binary field on the attachment row (object name is site-specific)
content = dc.download_file(
entry_id=attachment_id,
field_id="File", # Binary field on Attachment object
)Batch Download Pattern
Download multiple files:
def download_all_attachments(dc, object_id, entry_id, output_dir):
"""Download all attachments for an entry."""
from pathlib import Path
output = Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
fields = dc.get_fields(object_id)
attachment_fields = [f for f in fields if f.isAttachment]
entry = dc.read_data(
object_id,
output="list",
fields=["EntryId"] + [f.apiName for f in attachment_fields],
query=f"{{EntryId: {entry_id}}}",
)[0]
downloaded = []
for field in attachment_fields:
ref = entry.get(field.apiName)
if not ref:
continue
refs = ref if isinstance(ref, list) else [ref]
for r in refs:
att_id = r["id"] if isinstance(r, dict) else r
info = dc.download_attachment_metadata("Attachment", att_id, "File")
content = dc.download_file(entry_id=att_id, field_id="File")
fname = info.get("fileName") or f"{att_id}_file"
filepath = output / fname
filepath.write_bytes(content)
downloaded.append(str(filepath))
return downloaded
files = download_all_attachments(dc, "Deal", 12345, "./downloads")
print(f"Downloaded {len(files)} files")Stream Large Files
Prefer output_path so the REST client streams to disk instead of buffering the full body in memory:
path = dc.download_file(
entry_id=12345,
field_id="File",
output_path="large_file.zip",
)Error Handling
from intapp_rest_client.exceptions import HttpError
try:
content = dc.download_file(entry_id=12345, field_id="File")
except HttpError as e:
if e.status_code == 404:
print("File not found")
elif e.status_code == 403:
print("Permission denied")
else:
raiseCommon Patterns
Download with Correct Extension
def download_with_extension(dc, object_id, entry_id, field_id, output_dir):
"""Download file with a sensible filename from metadata."""
from pathlib import Path
import mimetypes
info = dc.download_attachment_metadata(object_id, entry_id, field_id)
ext = mimetypes.guess_extension(info.get("contentType") or "") or ""
filename = info.get("fileName") or f"{entry_id}_{field_id}{ext}"
content = dc.download_file(entry_id=entry_id, field_id=field_id)
output_path = Path(output_dir) / filename
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_bytes(content)
return str(output_path)
path = download_with_extension(dc, "Attachment", 12345, "File", "./downloads")Validate Before Download
def safe_download(dc, object_id, entry_id, field_id, max_size_mb=100):
"""Download with size validation using metadata first."""
info = dc.download_attachment_metadata(object_id, entry_id, field_id)
size = info.get("fileSize")
if size is None:
raise ValueError("Could not read file size from metadata")
size_mb = size / (1024 * 1024)
if size_mb > max_size_mb:
raise ValueError(f"File too large: {size_mb:.1f}MB > {max_size_mb}MB limit")
return dc.download_file(entry_id=entry_id, field_id=field_id)
content = safe_download(dc, "Attachment", 12345, "File", max_size_mb=50)Related
- Upload Files - Uploading files
- Bulk Export - Export many files
- Data API - Working with attachment references