Ant Design Upload 组件默认使用 XMLHttpRequest 且不走 axios/fetch,必须通过 customRequest 手动实现上传逻辑以支持 Authorization、timeout、onUploadProgress 及 application/xml 类型;需直接传 file 对象而非 FormData,并注意编码、响应类型与组件卸载防护。

Ant Design Upload 组件默认不走 axios 或 fetch,而是用原生 XMLHttpRequest
这是关键前提:即使你项目里全局用了 axios,Upload 的 customRequest 不显式覆盖,它就自己发请求,且无法携带 Authorization 头、无法设 timeout、无法监听 onUploadProgress —— 更别说上传 XML 文件时需要指定 Content-Type: application/xml。
必须用 customRequest 替换默认上传逻辑
XML 文件本质是二进制 Blob,但服务端通常要求明确的 Content-Type 和原始文本结构。直接传 file 对象给 FormData 会自动加 boundary,不适合纯 XML 场景。
-
customRequest函数接收{ file, onSuccess, onError, onProgress }四个参数,必须手动调用它们来控制状态 - 不要用
FormData.append('file', file)—— 这会让服务端收到 multipart 包裹体,而多数 XML 接口期望裸 XML 字符串或原始字节流 - 推荐读取为
text后用Blob构造新对象,或直接用file(如果服务端接受原始application/xml) -
onProgress只在XMLHttpRequest.upload上可用,fetch原生不支持上传进度,所以这里仍建议用XMLHttpRequest
customRequest: ({ file, onSuccess, onError, onProgress }) => {
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
onProgress({ percent: (e.loaded / e.total) * 100 });
}
};
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
onSuccess(xhr.response);
} else {
onError(new Error(Upload failed: ${xhr.status} ${xhr.statusText}));
}
};
xhr.onerror = () => onError(new Error('Network error'));
xhr.open('POST', '/api/upload-xml');
xhr.setRequestHeader('Content-Type', 'application/xml');
// 如果需要鉴权
// xhr.setRequestHeader('Authorization', Bearer ${token});
xhr.send(file);
}
XML 文件内容校验和编码问题要提前处理
浏览器读取 XML 文件时,file.text() 会按 UTF-8 解码;但如果文件含 BOM 或声明了 ,直接上传可能被服务端拒绝。稳妥做法是跳过解析,原样上传字节流 —— 这正是 xhr.send(file) 的优势。
- 避免先
file.text().then(str => new Blob([str], ...)),这会二次编码,可能破坏原始声明 - 若必须预览或校验内容,用
new FileReader().readAsText(file, 'UTF-8')并捕获异常,但上传仍用原始file对象 -
后端若返回非 JSON 响应(比如纯 XML 成功响应),注意
xhr.responseType设置(如'document'或''),否则xhr.response可能为空
React 18 下注意 customRequest 的异步稳定性
如果上传中组件卸载,onSuccess 或 onError 调用时可能触发 “Cannot update a component while rendering” 报错。需加简单清理机制:
- 在
customRequest内部声明一个isMounted = true,xhr.onload前判断 - 或用
useRef存储挂载状态,在useEffect(() => () => { isMounted.current = false }, []) - 更轻量的做法:只确保
onSuccess/onError是函数再调用,Ant Design 内部已做基础防护,但业务侧状态更新仍需自行守卫
XML 上传真正麻烦的不是格式本身,而是服务端对 Content-Type、编码、响应体类型的隐式约定 —— 动手前先 curl -v -H "Content-Type: application/xml" --data-binary @test.xml 验证通路,比调半天 React 逻辑更省时间。










