background_download
后台 URLSession 大文件下载。
后台 URLSession 大文件下载:App 进入后台后仍可继续,适合较大文件。
边界:使用系统后台URLSession,通过task_id轮询status()获取结果。前台小文件下载请用 network 的download()。destination_path需为 App 可写路径;下载启动放在按钮回调,不要在body()里自动发起。
#模块概览
| 项 | 说明 |
|---|---|
| 导入 | import background_download |
| 适合做什么 | 大 JSON/媒体包后台拉取、断点续传式后台任务 |
| 调用时机 | 用户确认后 download();用 Timer 或按钮轮询 status() |
| 推荐顺序 | download() 拿 task_id → 轮询 status() → 读 path |
| 状态机 | running → completed / failed / cancelled |
#快速开始
下面脚本发起下载并轮询状态:
已复制
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 刷新进度状态。
已复制
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)
已复制
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) 返回:
| 字段 | 说明 |
|---|---|
state | running / completed / failed / cancelled / unknown |
progress | 0.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 等元数据 |
#预期效果
运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。