XML上传需显式设置Content-Type为text/xml或application/xml;字符串需手动设头,File/Blob建议显式声明;FormData上传必须用Blob包装并指定文件名,且不可手动设Content-Type。
Content-Type 为 text/xml 或 application/xml
Axios 默认会根据请求数据自动推断 Content-Type,但对 XML 字符串或 Blob 不会设为 text/xml,容易被后端拒收或解析失败。必须显式指定,否则服务端可能按 application/json 或 application/x-www-form-urlencoded 解析,导致 400 错误或 XML 解析异常。
常见错误现象:400 Bad Request、Unexpected token (前端误当 JSON 解析)、后端日志显示“invalid content type”。
headers 中必须加 Content-Type: text/xml
File 或 Blob 对象(如用户选择的 .xml 文件),Content-Type 可设为 text/xml 或留空(浏览器通常能根据文件扩展名自动设为 text/xml),但显式声明更可靠application/xhtml+xml —— 它语义不同,多数后端不支持FormData 上传 XML 文件时不能直接 append 字符串如果后端接口要求以 multipart/form-data 方式接收 XML(例如同时传文件 + 其他字段),必须把 XML 包装成 File 或 Blob 后再 append 到 FormData。直接 append('file', xmlString) 会导致内容被当作普通文本字段,无文件名、无类型,后端无法识别为上传文件。
实操建议:
获取的 File 对象可直接 append('xml_file', file)
Blob:const blob = new Blob([xmlString], { type: 'text/xml' });
formData.append('xml_file', blob, 'data.xml');'data.xml' 是可选的文件名,强烈建议提供 —— 某些后端依赖它判断内容类型或做路由分发axios.post(url, xmlString) 直传(无 FormData)虽然技术上可行,但这种方式绕过浏览器原生文件上传机制,丢失了进度事件、取消能力、以及服务端对 multipart 的标准处理路径。且在跨域场景下易触发预检(OPTIONS),而预检请求不含 Content-Type,可能导致后端拒绝后续实际请求。
更稳妥的做法是统一走 FormData 路径,即使只传一个 XML 文件:
const formData = new FormData();
formData.append('xml_file', xmlBlob, 'request.xml');
axios.post('/api/upload', formData, {
headers: {
// 注意:不要手动设置 Content-Type!
// 让浏览器自动生成 boundary 的 multipart 头
},
timeout: 30000
});
关键点:不要给 FormData 请求手动设置 Content-Type —— Axios 会覆盖它,且浏览器需要自己生成带 boundary 的完整头;手动设置反而会导致 boundary 缺失,后端解析失败。
XML 上传是否成功,一半取决于前端构造,另一半取决于后端如何读取。比如:
multipart/form-data:用 @RequestParam MultipartFile file,此时前端必须用 FormData 且 append 键名与后端参数名一致multipart,需 
multer;若后端用 req.body 试图读 XML 字符串,则前端应走纯 POST 字符串方式(并显式设 Content-Type: text/xml)FormData,改用 axios.post(url, xmlString, { headers: { 'Content-Type': 'text/xml' } })
最常被忽略的一点:XML 声明行(如 )必须编码为 UTF-8,且前端传入的字符串或 Blob 必须真实使用 UTF-8 编码——用 new TextEncoder().encode() 或确保编辑器/输入源未混入 BOM 或其他编码。