Apache Commons FileUpload 是檔案上傳的經典元件,但在處理 multipart/mixed 巢狀結構 且包含自訂 Header 時,會遺失內層部分的 FileItemHeaders。本文從源碼 FileUploadBase.findNextItem() 切入,定位缺陷並提供最小侵入性修復方案。
X-File-Meta: {...})。ServletFileUpload.parseRequest(req) 解析。FileItemStream 後,呼叫 getHeaders() 發現自訂 Header 遺失,僅剩 Content-Disposition、Content-Type。FileUploadBase.findNextItem()關鍵邏輯(簡化):
FileItemHeaders headers = getParsedHeaders(multi.readHeaders());
// ... 解析 fieldName、fileName ...
// 外層 part:建立 FileItemStreamImpl(fileName, fieldName, contentType, isFormField, contentLength)
// 內層 part (巢狀 multipart/mixed):
// 原始碼:currentItem = new FileItemStreamImpl(fileName, currentFieldName, headers.getHeader(CONTENT_TYPE), false, getContentLength(headers));
// 缺陷:未將 headers 傳入建構子!
FileItemStreamImpl:FileItemStreamImpl(String pName, String pFieldName, String pContentType,
boolean pFormField, long pContentLength, FileItemHeaders headers)
throws IOException {
// ... 原有初始化 ...
if (headers != null) {
this.headers = headers; // 關鍵:保存完整 Headers
}
// ... 流初始化 ...
}
findNextItem() 內層分支呼叫新建構子:currentItem = new FileItemStreamImpl(fileName, currentFieldName,
headers.getHeader(CONTENT_TYPE), false,
getContentLength(headers), headers); // 透傳 headers
若專案無法升級元件版本,可採用 Java Agent / ByteBuddy 執行期重定義類別:
new AgentBuilder.Default()
.type(named("org.apache.commons.fileupload.FileUploadBase$FileItemStreamImpl"))
.transform((builder, typeDescription, classLoader, module) ->
builder.method(named("<init>").and(takesArguments(6)))
.intercept(MethodDelegation.to(FixHeadersInterceptor.class)))
.installOn(instrumentation);
或更簡單:將修復後的 FileUploadBase.class、FileItemStreamImpl.class 放入專案 WEB-INF/classes(類載入器優先級高於 Jar),即可覆蓋生效。
// 單元測試片段
FileItemStream item = upload.getItemIterator(req).next();
FileItemHeaders headers = item.getHeaders();
assertNotNull(headers.getHeader("X-File-Meta")); // 通過
此 Issue 已在 Commons FileUpload 1.4+ 修正(FILEUPLOAD-300),建議升級至 1.4 以上版本為根本解決。若受限於舊版相依,採用上述熱修復即可快速止血。
FileItemHeaders 中放入大型物件,Headers 會隨每個 part 駐留記憶體。commons-io 至 2.11+,避免 LimitedInputStream 相關記憶體洩漏。深入源碼定位並修復第三方元件 Bug,是資深工程師不可或缺的核心能力;掌握熱修復技術更能在無法升級依賴時從容應對。