= files()
:description: Downloads all file variants of an ECM document object from the server (std.StoreInCacheById). Returns a list of JobResponseFile objects with file content and metadata.
:keywords: files, StoreInCacheById, file variants, JobResponseFile, document, download
:page-tags: api, dms

Downloads the files of a document object from the server via `std.StoreInCacheById`.
The document can be passed as a model instance or directly as a numeric ID.
Files can optionally be converted before transfer or have annotations burned in.

== Signature

[tabs]
====
Sync::
+
[source,python]
----
ecm.dms.files(
    model: ECMDocumentModel | int,
    *,
    flags: int = 1,
    convert: StoreInCacheByIdConversion = StoreInCacheByIdConversion.NONE,
    when_cold_then_tiff: bool = False,
    add_annotations: bool = False,
) -> list[JobResponseFile]
----

Async::
+
[source,python]
----
await ecm.dms.files(
    model: ECMDocumentModel | int,
    *,
    flags: int = 1,
    convert: StoreInCacheByIdConversion = StoreInCacheByIdConversion.NONE,
    when_cold_then_tiff: bool = False,
    add_annotations: bool = False,
) -> list[JobResponseFile]
----
====

== Parameters

[cols="1,1,3"]
|===
|Parameter |Default |Description

|`model`
|—
|`ECMDocumentModel` instance (its `id` is used) or a plain `int` document ID.

|`flags`
|`1`
|Controls which files are transferred:

`0` — document files and the DIA file are transferred. +
`1` — only the document files themselves (default). +
`2` — only the DIA file of the object.

|`convert`
|`NONE`
|Optional conversion applied before transfer (`StoreInCacheByIdConversion`):

`NONE` — no conversion (default). +
`PDF` — documents with main type 1, 2, 3, or 4 are converted to PDF. +
`MULTIPAGE_TIFF` — TIFF documents with main type 2 or 3 are merged into a single multi-page TIFF file.

|`when_cold_then_tiff`
|`False`
|When `True`, ASCII COLD files are returned in TIFF format. Only evaluated when `convert=NONE`.

|`add_annotations`
|`False`
|When `True`, image annotations are burned into the returned files.
|===

== Return value

A list of `JobResponseFile` objects. Small files are kept as a byte array in memory;
larger files are written to a temporary file on the filesystem.

Properties and methods of `JobResponseFile`:

[cols="1,3"]
|===
|Property / Method |Description

|`.name`
|Filename including extension (e.g. `"invoice.pdf"`).

|`.extension`
|File extension (e.g. `".pdf"`).

|`.size()`
|File size in bytes.

|`.bytes()`
|File content as `bytes`. For file-path type, the content is read from disk and cached in memory on first call.

|`.store(path=None)`
|Write the file to disk. Without `path`, the system temporary directory is used. Returns the storage path.
|===

== Exceptions

`ValueError`:: `model` is an `ECMDocumentModel` instance with `id = None`.

== Examples

=== Load files from a model instance

[tabs]
====
Sync::
+
[source,python]
----
document = ecm.dms.get(InvoiceDocument, 12345)
for f in ecm.dms.files(document):
    print(f.name, f.size())
    content = f.bytes()
----

Async::
+
[source,python]
----
document = await ecm.dms.get(InvoiceDocument, 12345)
for f in await ecm.dms.files(document):
    print(f.name, f.size())
    content = f.bytes()
----
====

=== Load files by plain ID

If the document ID is known, the object does not need to be fully loaded:

[tabs]
====
Sync::
+
[source,python]
----
for f in ecm.dms.files(12345):
    print(f.name, f.size())
----

Async::
+
[source,python]
----
for f in await ecm.dms.files(12345):
    print(f.name, f.size())
----
====

=== Load as PDF

Documents with main types 1–4 are converted to PDF on the server before transfer:

[tabs]
====
Sync::
+
[source,python]
----
from ecmind_blue_client import StoreInCacheByIdConversion

files = ecm.dms.files(12345, convert=StoreInCacheByIdConversion.PDF)
pdf = files[0]
print(pdf.name)          # e.g. "invoice.pdf"
pdf.store("/tmp/invoice.pdf")
----

Async::
+
[source,python]
----
from ecmind_blue_client import StoreInCacheByIdConversion

files = await ecm.dms.files(12345, convert=StoreInCacheByIdConversion.PDF)
pdf = files[0]
pdf.store("/tmp/invoice.pdf")
----
====

=== Load as multi-page TIFF

TIFF documents (main types 2 or 3) are merged into a single multi-page TIFF file:

[tabs]
====
Sync::
+
[source,python]
----
from ecmind_blue_client import StoreInCacheByIdConversion

files = ecm.dms.files(12345, convert=StoreInCacheByIdConversion.MULTIPAGE_TIFF)
tiff = files[0]
tiff.store("/tmp/document.tiff")
----

Async::
+
[source,python]
----
from ecmind_blue_client import StoreInCacheByIdConversion

files = await ecm.dms.files(12345, convert=StoreInCacheByIdConversion.MULTIPAGE_TIFF)
tiff = files[0]
tiff.store("/tmp/document.tiff")
----
====

=== Load with burned-in annotations

[tabs]
====
Sync::
+
[source,python]
----
files = ecm.dms.files(12345, add_annotations=True)
for f in files:
    f.store(f"/tmp/{f.name}")
----

Async::
+
[source,python]
----
files = await ecm.dms.files(12345, add_annotations=True)
for f in files:
    f.store(f"/tmp/{f.name}")
----
====

=== Download all files from a query result

[tabs]
====
Sync::
+
[source,python]
----
import os

output_dir = "/tmp/invoices"
os.makedirs(output_dir, exist_ok=True)

for doc in ecm.dms.select(InvoiceDocument).where(InvoiceDocument.Year == 2024).stream():
    for f in ecm.dms.files(doc):
        f.store(os.path.join(output_dir, f"{doc.system.id}_{f.name}"))
----

Async::
+
[source,python]
----
import os

output_dir = "/tmp/invoices"
os.makedirs(output_dir, exist_ok=True)

async for doc in ecm.dms.select(InvoiceDocument).where(InvoiceDocument.Year == 2024).stream():
    for f in await ecm.dms.files(doc):
        f.store(os.path.join(output_dir, f"{doc.system.id}_{f.name}"))
----
====

== See also

* xref:api/dms/get.adoc[get()] — Load a single document by its ID
* xref:api/dms/insert.adoc[insert()] — Create a new document with a file
* xref:api/dms/update.adoc[update()] — Replace the file of an existing document
