Skip to content

Download Api Wrapped

immichpy.client.wrapper.download_api_wrapped.DownloadApiWrapped

DownloadApiWrapped(api_client=None)

Bases: DownloadApi

Wrapper for the DownloadApi that provides convenience methods.

Source code in immichpy/client/generated/api/download_api.py
32
33
34
35
def __init__(self, api_client=None) -> None:
    if api_client is None:
        api_client = ApiClient.get_default()
    self.api_client = api_client

download_archive_to_file async

download_archive_to_file(download_info: DownloadInfoDto, out_dir: Path, key: StrictStr | None = None, slug: StrictStr | None = None, show_progress: bool = False, **kwargs: Any) -> list[Path]

Download one or more asset archives and save them to ZIP files.

Note: This method intentionally downloads archives sequentially (not in parallel) by default. Immich has to build ZIP archives server-side; parallelizing many archive requests can put significant CPU/disk load on the Immich server and may lead to timeouts or degraded performance for other users. If you choose to parallelize, keep concurrency low and do so at your own risk.

Parameters:

Name Type Description Default
download_info DownloadInfoDto

The download info (two-step flow; downloads all archives returned by get_download_info).

required
out_dir Path

The directory to write the ZIP archive to.

required
key StrictStr | None

Public share key (the last path segment of a public share URL, i.e. /share/<key>). Allows access without authentication. Typically you pass either key or slug.

None
slug StrictStr | None

Public share slug for custom share URLs (the last path segment of /s/<slug>). Allows access without authentication. Typically you pass either slug or key.

None
show_progress bool

Whether to show progress bars (per-archive bytes + overall archive count).

False
kwargs Any

Additional arguments to pass to the underlying SDK calls.

{}

Returns:

Type Description
list[Path]

The list of paths to the downloaded archives.

For exact request/response behavior, inspect DownloadApi.download_archive_without_preload_content in the generated client.

Source code in immichpy/client/wrapper/download_api_wrapped.py
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
async def download_archive_to_file(
    self,
    download_info: DownloadInfoDto,
    out_dir: Path,
    key: StrictStr | None = None,
    slug: StrictStr | None = None,
    show_progress: bool = False,
    **kwargs: Any,
) -> list[Path]:
    """
    Download one or more asset archives and save them to ZIP files.

    Note: This method intentionally downloads archives **sequentially** (not in parallel) by default.
    Immich has to build ZIP archives server-side; parallelizing many archive requests can put significant
    CPU/disk load on the Immich server and may lead to timeouts or degraded performance for other users.
    If you choose to parallelize, keep concurrency low and do so at your own risk.

    :param download_info: The download info (two-step flow; downloads all archives returned by `get_download_info`).
    :param out_dir: The directory to write the ZIP archive to.
    :param key: Public share key (the last path segment of a public share URL, i.e. `/share/<key>`). Allows access without authentication. Typically you pass either `key` or `slug`.
    :param slug: Public share slug for custom share URLs (the last path segment of `/s/<slug>`). Allows access without authentication. Typically you pass either `slug` or `key`.
    :param show_progress: Whether to show progress bars (per-archive bytes + overall archive count).
    :param kwargs: Additional arguments to pass to the underlying SDK calls.

    :return: The list of paths to the downloaded archives.

    For exact request/response behavior, inspect `DownloadApi.download_archive_without_preload_content`
    in the generated client.
    """
    out_dir.mkdir(parents=True, exist_ok=True)

    # Normalize to a list of archive requests.
    info = await super().get_download_info(
        download_info, key=key, slug=slug, **kwargs
    )
    archive_requests: list[tuple[DownloadArchiveDto, int]] = [
        (
            DownloadArchiveDto(
                assetIds=[UUID(str(asset_id)) for asset_id in archive.asset_ids]
            ),
            int(archive.size),
        )
        for archive in info.archives
    ]

    out_paths: list[Path] = []

    progress_columns = [
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        BarColumn(),
        TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
        DownloadColumn(),
        TransferSpeedColumn(),
        TimeRemainingColumn(),
    ]

    with Progress(*progress_columns, disable=not show_progress) as progress:
        archives_task = progress.add_task(
            f"[cyan]Downloading {len(archive_requests)} archives",
            total=len(archive_requests),
        )
        for download_archive_dto, expected_size in archive_requests:
            filename = f"archive-{uuid4()}.zip"

            def make_request(extra_headers: HeadersType | None):
                return self.download_archive_without_preload_content(
                    download_archive_dto=download_archive_dto,
                    key=key,
                    slug=slug,
                    _headers=kwargs.get("_headers", {}) | (extra_headers or {}),
                    **kwargs,
                )

            download_task = progress.add_task(
                f"[green]{filename}",
                total=expected_size or None,
            )
            await download_file(
                make_request=make_request,
                out_dir=out_dir,
                resolve_filename=lambda headers: filename,
                show_progress=show_progress,
                progress=progress,
                task_id=download_task,
                resumeable=False,  # zip files are not resumable
            )
            out_paths.append(out_dir / filename)
            progress.update(archives_task, advance=1)

    return out_paths