Ajax下载XML文件始终进入错误回调,求排查解决
问题描述
基于.NET WebAPI搭建接口处理Ajax请求:请求异常时返回含错误信息的JSON,成功则返回XML文件供下载。目前JSON错误响应可正常展示服务端错误信息,API能生成并返回文件(Postman测试可获取XML文件),但浏览器中发起Ajax请求时,本该接收文件的场景始终进入错误回调且err参数为空,无法触发文件下载,求问题原因及解决办法。
AJAX代码
let formData = { SomeData: { 'validation':'stuff' }, Token: m_securityToken }; $.ajax( { url: m_APIURL', method: 'POST', type: 'POST', data: JSON.stringify( formData ), contentType: 'application/json', xhrFields: { responseType: 'blob' }, crossDomain: true, success: function( blob, status, xhr ) { var disposition = xhr.getResponseHeader( 'Content-Disposition' ); if( disposition && disposition.indexOf( 'attachment' ) !== -1 ) { // 成功返回文件时触发下载 var filename = 'response.xml'; if( typeof window.navigator.msSaveBlob !== 'undefined' ) { // IE兼容处理 window.navigator.msSaveBlob( blob, filename ); } else { var URL = window.URL || window.webkitURL; var downloadUrl = URL.createObjectURL( blob ); var a = document.createElement( "a" ); if( typeof a.download === 'undefined' ) { // Safari兼容处理 window.location.href = downloadUrl; } else { a.href = downloadUrl; a.download = filename; document.body.appendChild( a ); a.click(); } setTimeout( function() { URL.revokeObjectURL( downloadUrl ); }, 100 ); } } else { // 验证失败返回JSON时展示错误 if( blob != null ) { if( ( blob.ErrorMessage && blob.ErrorMessage != "OK" ) || ( !blob.Content || blob.Content == '' ) ) { alert( "获取许可证文件失败:" + blob.ErrorMessage ); } else { alert( "获取许可证文件失败:" + blob.Content ); } } else { alert( "获取许可证文件失败。" ); } } }, error: function( err ) { if( err != null && err.length > 0 ) { console.log( "响应错误:" + JSON.stringify( err ) ); } else { // 总是进入这个分支 console.log( "响应错误但未返回任何信息。" ); } } } );
API代码
[HttpPost, Route( "MyAPI/GetXMLFile" )] public IHttpActionResult GetXMLFile( CustomRequestModel requestModel ) { // 请求验证 if( !requestModel.IsValid() ) { responseModel.ErrorMessage = "无效请求。"; return Json( responseModel ); } // 生成XML响应内容 string rawResponseXML = CreateResponse( requestModel ); // 返回文件 HttpResponseMessage responseFile = new HttpResponseMessage( HttpStatusCode.OK ); responseFile.Content = new StringContent( rawReponseXML ); responseFile.Content.Headers.ContentType = new MediaTypeHeaderValue( "application/octet-stream" ); responseFile.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue( "attachment" ); responseFile.Content.Headers.ContentDisposition.FileName = "response.xml"; return ResponseMessage( responseFile ); }
问题原因及解决办法
1. 跨域响应头暴露问题
因为开启了crossDomain: true,跨域请求时浏览器会限制非简单响应头的获取,Content-Disposition属于此类。需要在WebAPI的CORS配置中允许暴露该头:
// 在Startup.cs的CORS配置中添加 app.UseCors(builder => builder .AllowAnyOrigin() // 建议根据实际业务调整,避免过度开放 .AllowAnyMethod() .AllowAnyHeader() .WithExposedHeaders("Content-Disposition"));
2. Blob转JSON的错误处理逻辑
设置responseType: 'blob'后,JSON错误响应也会被转为Blob,无法直接读取属性,需手动转成JSON:
修改AJAX的success回调中错误处理部分:
else { // 将Blob转换为JSON解析错误信息 const reader = new FileReader(); reader.onload = function() { const errorData = JSON.parse(reader.result); if (errorData.ErrorMessage && errorData.ErrorMessage !== "OK" || !errorData.Content || errorData.Content === '') { alert("获取许可证文件失败:" + errorData.ErrorMessage); } else { alert("获取许可证文件失败:" + errorData.Content); } }; reader.readAsText(blob); }
3. API响应内容编码修正
使用StringContent返回XML时,指定UTF-8编码避免乱码,同时修正代码中的拼写错误(rawReponseXML改为rawResponseXML):
responseFile.Content = new StringContent(rawResponseXML, Encoding.UTF8, "application/octet-stream");
4. 排查错误回调触发根源
打开浏览器开发者工具的Network面板,查看实际响应的状态码、响应头是否正常,是否有CORS相关报错。常见触发错误回调的原因包括:
- 跨域响应头未正确配置
- 响应MIME类型与
responseType不兼容 - 服务端实际返回了非2xx状态码(比如500错误)
内容的提问来源于stack exchange,提问作者Trint
相关产品推荐
相关产品推荐

