PythonIDE Docs
中文
简体中文

background_download

后台 URLSession 大文件下载。

后台 URLSession 大文件下载:App 进入后台后仍可继续,适合较大文件。

边界:使用系统后台 URLSession,通过 task_id 轮询 status() 获取结果。前台小文件下载请用 networkdownload()destination_path 需为 App 可写路径;下载启动放在按钮回调,不要在 body() 里自动发起。

#模块概览

说明
导入import background_download
适合做什么大 JSON/媒体包后台拉取、断点续传式后台任务
调用时机用户确认后 download();用 Timer 或按钮轮询 status()
推荐顺序download()task_id → 轮询 status() → 读 path
状态机runningcompleted / failed / cancelled

#快速开始

下面脚本发起下载并轮询状态:

python
import os
import time
import background_download

dest = os.path.join(os.path.expanduser("~/Documents"), "httpbin.json")

try:
    task_id = background_download.download(
        "https://httpbin.org/json",
        dest,
    )
    print("任务:", task_id)

    for _ in range(30):
        st = background_download.status(task_id)
        print(st.get("state"), st.get("progress"))
        if st.get("state") in ("completed", "failed", "cancelled"):
            break
        time.sleep(1)

    if st.get("state") == "completed":
        print("已保存:", st.get("path"))
    elif st.get("error"):
        print("失败:", st.get("error"))
except background_download.BackgroundDownloadError as exc:
    print("下载失败:", exc, f"code={exc.code}")

#AppUI 示例

下载和轮询放在按钮回调;用 Timer 刷新进度状态。

python
import appui
import os
import background_download

DEST = os.path.join(os.path.expanduser("~/Documents"), "demo-download.json")
URL = "https://httpbin.org/json"

state = appui.State(
    task_id="",
    dl_state="空闲",
    progress="—",
    status="点击开始下载",
)


def poll():
    if not state.task_id:
        return
    try:
        st = background_download.status(state.task_id) or {}
        dl_state = st.get("state", "unknown")
        prog = st.get("progress", 0.0)
        state.batch_update(
            dl_state=dl_state,
            progress=f"{float(prog) * 100:.0f}%",
        )
        if dl_state == "completed":
            poll_timer.stop()
            state.status = f"完成: {st.get('path', DEST)}"
        elif dl_state == "failed":
            poll_timer.stop()
            state.status = f"失败: {st.get('error', '未知错误')}"
        elif dl_state == "cancelled":
            poll_timer.stop()
            state.status = "已取消"
    except background_download.BackgroundDownloadError as exc:
        poll_timer.stop()
        state.status = f"查询失败: {exc}"


poll_timer = appui.Timer(interval=0.5, repeats=True, action=poll)


def start_download():
    try:
        task_id = background_download.download(URL, DEST)
        state.batch_update(
            task_id=task_id or "",
            dl_state="running",
            progress="0%",
            status="下载中…",
        )
        poll_timer.start()
    except background_download.BackgroundDownloadError as exc:
        state.status = f"启动失败: {exc}"


def cancel_download():
    if not state.task_id:
        return
    try:
        background_download.cancel(state.task_id)
        poll_timer.stop()
        state.batch_update(dl_state="cancelled", status="已请求取消")
    except background_download.BackgroundDownloadError as exc:
        state.status = f"取消失败: {exc}"


def body():
    return appui.NavigationStack(
        appui.Form([
            appui.Section("任务", [
                appui.LabeledContent("状态", value=state.dl_state),
                appui.LabeledContent("进度", value=state.progress),
                appui.Text(state.task_id or "—")
                .font("caption")
                .foreground_color("secondaryLabel"),
            ]),
            appui.Section("操作", [
                appui.Button("开始后台下载", action=start_download)
                .button_style("bordered_prominent"),
                appui.Button("取消", action=cancel_download, role="destructive"),
                appui.Text(state.status).foreground_color("secondaryLabel"),
            ], footer="需网络;大文件更适合后台下载。"),
        ]).navigation_title("后台下载")
    )


appui.run(body, state=state)

#API 参考

#速查

API作用
download(url, destination_path, task_id)开始下载 → task_id
status(task_id){state, progress, path, error}
cancel(task_id)取消任务
BackgroundDownloadError操作失败时抛出

#download

download(url, destination_path, task_id=None)

python
task_id = background_download.download(
    "https://example.com/file.zip",
    "/path/to/save.zip",
)
参数说明
url下载地址
destination_path保存路径(App 可写)
task_id可选自定义 ID;省略时自动生成 UUID

#status

status(task_id) 返回:

字段说明
staterunning / completed / failed / cancelled / unknown
progress0.0–1.0(完成时为 1.0)
path目标路径(完成后有效)
error失败时的错误信息

建议轮询间隔 ≥ 0.5 秒。

#cancel

cancel(task_id) — 取消进行中的任务,状态变为 cancelled


#常见错误

错误写法后果修正
body()download()刷新时重复下载放进按钮回调
destination_path 不可写移动文件失败用 Documents 等沙盒路径
不轮询 status()不知道何时完成Timer 或循环查询
小文件也用后台下载过度复杂前台用 network

#相关文档

文档用途
network前台 HTTP / 小文件下载
background后台任务保活
storage记录 task_id 等元数据

#预期效果

运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。