任務顯示完成,下載卻是空檔?把執行和交付狀態拆開
按鈕寫著「完成」,點下載卻拿到空文件?問題往往不在提示文字,而是後端只記了演算法跑完,沒記交付是否就緒。把執行狀態和交付狀態拆開,前端才能告訴用戶真實進度,本文講清拆分思路。
任務頁顯示“完成”,點下載卻拿到空文件,問題往往不在提示文字本身,而是後端只記錄了算法執行結束,沒有記錄交付是否就緒。 這篇文章寫給正在做文件處理、非同步任務或翻譯整合的開發者。 讀完後,你會知道如何把執行狀態和交付狀態拆開,讓前端向使用者展示真實進度。
文中示例使用合成樣本,代碼在隔離環境中做過示例檢查,這不代表對所有真實文件或產品效果的保證。 處理重要文件前,請保留原件,並按文中的邊界與驗收項複核。
下載是空文件,任務卻顯示完成?一句話結論
先把“處理完成”拆成處理、產物和驗收三個狀態,再讓前端只展示已經確認的狀態。
| 你的情況 | 推薦做法 | 原因 |
|---|---|---|
| 任務已結束,但檔案還沒生成 | 進入“產物就緒”狀態,不提前顯示可下載 | 處理結束只說明計算停止,不代表有可定位文件 |
| 檔案已生成,但內容還沒檢查 | 保持“正在檢查結果”,等待驗收 | 產物就緒不等於滿足交付協議 |
| 任務失敗 | 顯示失敗階段和原因,並給出對應動作 | 失敗也應帶階段,不能用旋轉圖示隱藏 |
| 下載返回 HTTP 200 | 繼續檢查類型、大小、解析可用性和預期內容 | 200 可能對應登入頁、錯誤 JSON 或空白文件 |
至少區分處理、產物和驗收
處理結束表示計算停止;產物就緒表示有可定位檔;驗收完成表示文件符合交付協議。三者不一定在同一時刻發生。
失敗也應該帶階段,不能靠一個永久旋轉的圖示隱藏。 用戶知道是在處理、生成還是檢查時出錯,才知道該等待、重試還是修復輸入。
📊 核心對比
| 狀態 | 回答的問題 | 能否對用戶承諾下載 |
|---|---|---|
| 處理結束 | 計算是否已經停止 | 不能 |
| 產物就緒 | 是否有可定位的檔案 | 不能,仍需檢查 |
| 驗收完成 | 文件是否滿足交付協議 | 可以 |
顯式拒絕跳躍式成功
from enum import Enum
class State(Enum):
PROCESSING = "processing"
ARTIFACT_READY = "artifact_ready"
VERIFIED = "verified"
FAILED = "failed"
def transition(state, event):
allowed = {
(State.PROCESSING, "stored"): State.ARTIFACT_READY,
(State.PROCESSING, "error"): State.FAILED,
(State.ARTIFACT_READY, "checks_passed"): State.VERIFIED,
(State.ARTIFACT_READY, "error"): State.FAILED,
}
if (state, event) not in allowed:
raise ValueError("invalid state transition")
return allowed[(state, event)]
s = transition(State.PROCESSING, "stored")
assert s is State.ARTIFACT_READY
assert transition(s, "checks_passed") is State.VERIFIED
assert transition(s, "error") is State.FAILED
try:
transition(State.PROCESSING, "checks_passed")
except ValueError:
pass
else:
raise AssertionError("cannot skip artifact readiness")
這個合成狀態機不包含佇列取消、重新審校和過期刪除。 生產實現應根據業務擴展,而不是把所有事件塞進「成功/失敗」二選一。
非同步消息還可能重複或亂序,需要版本號、事務和冪等處理配合。 否則,舊訊息可能覆蓋新狀態,同一任務也可能被重複寫入。
前端提示應與事實對應
前端每個狀態都應對應後端可以確認的事實,並給出相應的可用動作。
| 狀態 | 用戶可以看到 | 可用動作 |
|---|---|---|
| processing | 正在處理 | 查看進度或取消 |
| artifact_ready | 正在檢查結果 | 不提前承諾可用 |
| verified | 檔案可下載 | 下載與查看驗收說明 |
| failed | 失敗階段與原因 | 按原因修復或重試 |
下載成功也不是內容正確
HTTP 200 可能返回登入頁、錯誤 JSON 或空白文件。 驗收至少應檢查以下幾項:
- 類型:檔案格式是否符合預期
- 大小:檔案是否為空或明顯異常
- 解析可用性:檔案能否被正常打開和解析
- 預期內容:內容是否與任務要求一致
對於翻譯,語言完整性與術語審查是更上層的檢查,不應被「檔案能開啟」替代。
集成翻譯能力時保持狀態透明
接入OmniDoc(產品入口)後,自有產品仍應維護自己的儲存與交付狀態。 平台任務完成後,可以先映射為“開始接收結果”,確認文件可用後再顯示成功。 這樣比直接透傳一個狀態更符合用戶的實際體驗。
參考資料:Python enum
🎯 哪種做法適合你?
如果你......
如果你的任務只是後台計算,沒有對外交付檔案
只需記錄處理結束與失敗階段,產物和驗收可以暫時省略。
如果你需要讓用戶下載結果
必須等產物就緒並通過驗收,再顯示可下載。
如果你接入了第三方處理平台
把平台完成映射為“開始接收結果”,確認文件後再顯示成功。
如果任務可能重複或亂序返回
為狀態加入版本號,並通過事務和冪等處理保證狀態只向前推進。
❓ 常見問題(FAQ)
1. 任務顯示完成,為什麼還不能下載?
因為處理結束只表示計算停止,還需要確認產物就緒,並通過驗收,才表示文件滿足交付協議。
2. 下載返回 HTTP 200,是不是說明檔案沒問題?
不一定。 HTTP 200 可能返回登入頁、錯誤 JSON 或空白文件,還需要檢查類型、大小、解析可用性和預期內容。
3. 失敗狀態為什麼要帶階段?
失敗階段能告訴用戶問題出在處理、生成還是檢查環節,便於他們決定等待、重試還是修復輸入。
4. 翻譯任務只要檔案能打開就夠了嗎?
不夠。 語言完整性與術語審查是更上層的檢查,不應被「檔案能開啟」替代。
📝 總結
把執行狀態和交付狀態拆開,前端才能告訴用戶真實進度。 只有產物就緒並通過驗收,才應顯示可下載。


