任務顯示完成,下載卻是空檔?把執行和交付狀態拆開

按鈕寫著「完成」,點下載卻拿到空文件?問題往往不在提示文字,而是後端只記了演算法跑完,沒記交付是否就緒。把執行狀態和交付狀態拆開,前端才能告訴用戶真實進度,本文講清拆分思路。

任務頁顯示“完成”,點下載卻拿到空文件,問題往往不在提示文字本身,而是後端只記錄了算法執行結束,沒有記錄交付是否就緒。 這篇文章寫給正在做文件處理、非同步任務或翻譯整合的開發者。 讀完後,你會知道如何把執行狀態和交付狀態拆開,讓前端向使用者展示真實進度。

文中示例使用合成樣本,代碼在隔離環境中做過示例檢查,這不代表對所有真實文件或產品效果的保證。 處理重要文件前,請保留原件,並按文中的邊界與驗收項複核。

下載是空文件,任務卻顯示完成?一句話結論

先把“處理完成”拆成處理、產物和驗收三個狀態,再讓前端只展示已經確認的狀態。

你的情況推薦做法原因
任務已結束,但檔案還沒生成進入“產物就緒”狀態,不提前顯示可下載處理結束只說明計算停止,不代表有可定位文件
檔案已生成,但內容還沒檢查保持“正在檢查結果”,等待驗收產物就緒不等於滿足交付協議
任務失敗顯示失敗階段和原因,並給出對應動作失敗也應帶階段,不能用旋轉圖示隱藏
下載返回 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. 翻譯任務只要檔案能打開就夠了嗎?

不夠。 語言完整性與術語審查是更上層的檢查,不應被「檔案能開啟」替代。

📝 總結

把執行狀態和交付狀態拆開,前端才能告訴用戶真實進度。 只有產物就緒並通過驗收,才應顯示可下載。

立即體驗:上傳文件即可開始翻譯,保留原排版

更新於 2026-11-14