SSE 实时进度
通过 SSE(Server-Sent Events)实时接收文件翻译任务(/jobs)的进度。SSE 未开放时连接返回 404,请改为轮询任务状态。
浏览器的 EventSource 不支持自定义 Header,因此采用两步凭据方式:
- 用 API Key 换取 ticket(30 秒内有效,只能使用一次)
- 用 ticket 建立 SSE 连接
POST /api/v1/sse/ticket/{job_id} → {"ticket": "..."}GET /api/v1/sse/jobs/{job_id}?ticket=...JavaScript 示例
Section titled “JavaScript 示例”// 1. 换取 ticket(普通 API Key 认证)const { ticket } = await fetch( `https://omnidoc.top/api/v1/sse/ticket/${jobId}`, { method: 'POST', headers: { 'X-API-Key': API_KEY } }).then(r => r.json());
// 2. 用 ticket 连接 SSEconst source = new EventSource( `https://omnidoc.top/api/v1/sse/jobs/${jobId}?ticket=${ticket}`);
// 事件是命名事件,用 addEventListener(onmessage 收不到)source.addEventListener('job_update', (event) => { const data = JSON.parse(event.data); console.log(`状态: ${data.status}, 阶段: ${data.stage}, 进度: ${data.stage_progress}%`);});
source.addEventListener('job_done', (event) => { const data = JSON.parse(event.data); console.log(`结束: ${data.status}`); source.close();});| 事件 | 说明 |
|---|---|
job_update | 状态/阶段变化(连接后先推一次当前快照) |
job_done | 任务结束(completed 或 failed),此后可关闭连接 |
timeout | 流达到最长时限,需重新连接 |
error | 服务端异常,稍后重新换取 ticket 连接 |
事件数据格式
Section titled “事件数据格式”event: job_updatedata: {"status":"processing","stage":"translating","stage_progress":45,"stage_message":"正在翻译..."}
event: job_donedata: {"status":"completed","stage":"completed","stage_progress":100,"stage_message":""}任务完成后通过 GET /api/v1/artifacts?job_id=... 获取产物列表。
Python 示例
Section titled “Python 示例”import jsonimport requestsimport sseclient
ticket = requests.post( f"{BASE}/sse/ticket/{job_id}", headers=HEADERS).json()["ticket"]
response = requests.get( f"{BASE}/sse/jobs/{job_id}", params={"ticket": ticket}, stream=True)client = sseclient.SSEClient(response)
for event in client.events(): data = json.loads(event.data) print(f"[{event.event}] {data.get('stage')} {data.get('stage_progress', 0)}%") if event.event == "job_done": break- ticket 一次性有效,重连前需重新获取
- 长时间没有任务事件时,服务端会发送
timeout事件;需重新换取 ticket 并连接 - 连接闲置期间服务端会发送心跳注释,客户端应忽略注释行
- 如果连接断开,可用轮询
GET /jobs/{id}作为兜底