阿里雲代理帳號服務 阿裡雲 OSS SDK 上傳提示 400 InvalidPart:分片大小不一致與 MD5 校驗失敗
問題現象:400 InvalidPart 不只是上傳失敗
在使用阿裡雲 OSS SDK 做大檔上傳時,最讓人頭痛的錯誤之一就是 400 InvalidPart。表面上看,它只是一次分片上傳失敗;實際上,這類問題往往不是網絡波動那麼簡單,而是上傳流程中的某個約束被破壞了。最常見的兩種情況,一個是分片大小前後不一致,另一個是分片內容或計算方式發生變化,導致 MD5 校驗失敗。
很多人第一次遇到這個錯誤時,會直覺地認為「重新傳一次就好了」。有時候確實能碰巧成功,但如果根因沒有處理,下次還會再次出現。尤其是在斷點續傳、並發上傳、重試補傳這幾個場景裡,只要分片管理稍有疏忽,OSS 就可能在合併分片時直接拒絕請求。
常見表現
- 某一個 Part 上傳成功,但 CompleteMultipartUpload 時返回 400 InvalidPart。
- 前幾個分片正常,只有某個補傳的分片出錯。
- 本地看起來文件沒變,但服務端卻提示分片不合法。
- 阿里雲代理帳號服務 日誌中出現 ETag 不匹配、PartNumber 錯亂、MD5 校驗失敗等線索。
這類錯誤最容易迷惑人的地方在於:上傳接口本身可能返回 200,但最終合併時才報錯。也就是說,問題不一定發生在「傳」的那一步,而更可能出在「分片管理」「重試策略」「校驗值生成」這些看不見的細節上。
先看本質:OSS 為什麼會拒絕這個 Part
OSS 的分片上傳並不是把文件粗暴切成幾段直接丟上去,而是有一套很明確的流程:先發起分片上傳,獲得 uploadId;再按照 PartNumber 逐片上傳;最後把所有分片的編號與 ETag 一起提交給服務端完成合併。只要其中任一環節不一致,服務端就無法確認這些分片是否屬於同一個完整文件,也就會返回 InvalidPart。
從服務端視角看,它不關心你本地怎麼切文件,只關心三件事:這是不是同一次 multipart upload;每個分片的編號是否正確;分片內容與摘要是否與當前上傳記錄一致。只要有一項不符合,就可能被認定為無效分片。
分片大小不一致
阿里雲代理帳號服務 分片大小不一致是最常見的踩坑點。理論上,分片上傳時你可以自定義 chunk size,但一旦某次上傳使用的是 5MB,重試時卻變成了 6MB,或者前後兩次分片邊界發生偏移,OSS 看到的就不再是同一批 Part。更麻煩的是,有些業務在斷點續傳時只記錄了文件偏移,卻沒有同時記錄當時的分片大小,導致續傳後生成的 PartNumber 和實際內容對不上。
另一種情況是,開發者把最後一片的特殊邏輯寫得不夠嚴謹。OSS 允許最後一個分片小於既定大小,但前提是它仍然必須對應正確的文件尾部。如果你在計算偏移時把尾部切錯,或者因為讀流位置錯誤導致最後一片內容不是預期區間,服務端也會認為該 Part 無效。
MD5 校驗失敗
MD5 校驗失敗通常說明,OSS 收到的分片內容與客戶端聲稱的內容不一致。這種不一致有時候不是文件真的被改了,而是客戶端在計算 MD5 時與實際上傳內容不一致。例如,先把流讀了一遍計算摘要,然後又試圖直接拿同一個已讀到末尾的流去上傳;或者對文本文件做了編碼轉換,導致字節內容與原始文件不再相同。
阿里雲代理帳號服務 還有一類問題更隱蔽:重試時沒有重新生成內容摘要,而是沿用上一次失敗請求的 MD5。當分片內容已經變了,摘要卻沒變,服務端自然會判定不匹配。對於依賴臨時文件、內存緩衝區或加密壓縮流程的場景,任何一個中間環節都可能改變最終字節流,進而觸發校驗問題。
排查思路:先確認是哪一層出了問題
遇到 400 InvalidPart,不要急著改 SDK 版本,也不要只盯著上傳接口。最有效的做法,是把整個流程拆成三層來看:本地分片是否正確、上傳請求是否正確、服務端合併時是否拿到了同一批分片信息。只要逐層排查,很快就能定位問題。
第一步:檢查分片邊界
先確認每個 Part 的起始偏移、結束偏移、大小是否符合預期。最簡單的辦法,是在本地打印每個分片的序號、偏移量、長度以及文件指紋。只要其中一片的長度突然變了,或者同一個 PartNumber 對應了不同內容,問題就暴露了。
如果你使用並發上傳,務必確認分片編號是固定且唯一的。並發只是同時傳,不代表順序可以亂。合併時 OSS 是按 PartNumber 來識別分片的,而不是按完成時間。如果你的重試邏輯把兩個不同內容都寫進同一個 PartNumber,後續一定出問題。
第二步:檢查流是否被重用
很多語言的文件流一旦讀過,就會停在末尾。如果你先對流做了 MD5 計算,再把同一個流直接交給上傳 SDK,實際傳出去的可能是空內容或殘缺內容。這類錯誤在本地測試時未必立刻暴露,因為小文件、內存流或某些封裝類型看起來還能工作,但在真實大文件場景裡就會頻繁翻車。
更穩妥的做法是:要麼為計算摘要和上傳各準備一次可重新打開的流,要麼在內存或臨時文件中固定住分片內容,確保摘要與上傳字節完全一致。只要你無法保證流可重讀,就不應該把它當作一次性「讀完就算」的對象來用。
第三步:對照服務端返回值
OSS 在分片上傳成功後,通常會返回每個 Part 的 ETag。這個值非常關鍵,它相當於服務端對分片內容的指紋。當最終合併時,提交的 PartNumber 與 ETag 必須一一對應。如果你在本地保存 ETag 時發生覆蓋、丟失、排序錯亂,或者把別的 uploadId 的分片 ETag 混了進來,最終都會落到 InvalidPart 上。
因此,排查時不要只看「我傳過了沒有」,而要看「我保存下來的上傳記錄是不是完整」。對斷點續傳來說,這個問題尤其重要。你不但要保存 uploadId,還要保存每個已成功上傳的分片號、ETag、文件大小、分片大小、文件版本等信息,否則續傳時很難保證上下文一致。
修復方案:把上傳流程變得可控
真正有效的修復,不是臨時繞過錯誤,而是讓分片上傳變成一個可重放、可校驗、可恢復的流程。只要這套流程穩了,InvalidPart 的出現頻率會明顯下降。
統一分片大小與生成規則
分片大小要在整個上傳生命週期中保持穩定,尤其是在重試和續傳時不能隨意變更。最好的做法,是把 chunk size 作為任務級別配置,寫入上傳任務元數據中,而不是每次啟動時根據當前環境臨時決定。這樣不管是多進程、分布式任務還是失敗重試,分片邊界都能保持一致。
如果業務確實需要動態調整分片大小,也應該把它視為一個新任務,而不是舊任務的延續。因為一旦分片大小發生變化,原來保存的 PartNumber、偏移量和 ETag 幾乎都失去參考價值,沿用它們只會讓問題更隱蔽。
校驗內容而不是只校驗文件名
很多上傳任務只用文件名判定是否重試,這是不夠的。兩個同名文件內容可能完全不同,或者同一文件在生成後又被修改過。更可靠的方式,是在開始分片前先生成文件級別的校驗信息,比如大小、修改時間、整體摘要,必要時連同業務版本一起記錄。這樣一來,重試時就能確認自己處理的還是不是同一份文件。
對於需要強一致性的場景,可以在每個分片上都做局部校驗,並把結果保存下來。當某個分片出錯時,先比對本地緩存的內容與待上傳內容是否一致,再決定是否需要重新切片,而不是盲目補傳。
重試要重新計算,不要複用舊結果
分片上傳失敗後的重試,看起來只是再發一次請求,但實際上最好視為一次新的內容讀取。只要底層文件、緩衝區或流狀態可能發生變化,就應該重新計算該分片的內容、長度和摘要。不要把上一次失敗時的 MD5 或 ETag 當成「可復用資產」,因為它們只對那一次實際內容負責。
如果你的任務有並發控制,重試時還要防止同一個 PartNumber 被多個線程同時寫入。這種競態條件非常容易造成「看似成功,實際錯亂」的情況。最簡單的做法,是為每個分片建立明確的狀態機:待上傳、上傳中、成功、失敗、待重試。只有狀態清晰,後續合併才不會亂。
最佳實踐:把問題擋在上傳前
大多數 InvalidPart 並不是 OSS 脾氣不好,而是上傳前的準備工作不夠嚴謹。想少踩坑,關鍵不是「怎麼修錯」,而是「怎麼不讓錯誤進到服務端」。
建立上傳任務記錄
每次啟動分片上傳,都應該保存一份完整的任務記錄,包括 uploadId、文件標識、總大小、分片大小、已上傳分片列表、每個分片的 ETag 以及最後一次成功時間。這份記錄不僅能支持斷點續傳,也能在故障排查時快速定位問題。如果沒有這層記錄,很多看似偶發的錯誤其實都無法復現。
上傳前做本地預校驗
在真正調用 OSS 之前,先在本地檢查文件是否可讀、分片邊界是否正確、每片摘要是否可算、流是否支持重新打開。這些檢查成本很低,但能攔住大量低級錯誤。尤其是在多步處理鏈中,例如先壓縮再加密再上傳,建議在最終入庫前再做一次字節級別驗證,避免中間層改動內容卻沒被察覺。
為異常保留足夠日志
不要只記錄一句「上傳失敗」。真正有用的日志,至少要包含分片號、偏移量、長度、ETag、uploadId、錯誤碼和錯誤消息。當問題發生時,這些信息能幫你快速判斷是大小不一致、摘要不一致,還是分片記錄錯亂。沒有日志的上傳系統,排障往往只能靠猜。
結語:InvalidPart 的核心不是錯誤碼,而是流程失控
阿裡雲 OSS SDK 上傳提示 400 InvalidPart,從字面上看只是一次分片無效;但從工程角度看,它往往暴露的是整個上傳流程的不穩定。分片大小是否統一,流是否可重讀,重試是否重新計算,ETag 是否正確保存,這些看似瑣碎的細節,最後都會在合併階段集中爆發。
如果你只想短期修好,最快的方法是把分片規則固定住,避免流重用,並重新梳理重試邏輯。如果你想長期避免這類問題,則應該把分片上傳當成一個完整的任務系統來設計:有記錄、有校驗、有狀態、有回放能力。只要流程穩,400 InvalidPart 就不再是神秘故障,而只是一次可以被定位和修復的普通異常。

