You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core调用接口无法触发浏览器下载.json文件的解决方法

问题说明

Controller中实现JSON文件生成下载的代码如下:

public FileResult GenerateJSON()
{
    string filename = "aa.json";
    string filepath = VariableDeclarations.wwwPath + @"\Downloads\" + filename;
    string filedata = System.IO.File.ReadAllText(filepath);
    string contentType = GetContentType(filepath);

    var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = filename,
        Inline = true
            
    };

    HttpContext.Response.Headers.Add("Content-Disposition",$"attachment;filename=aa.json");

    return File(filedata, "application/json", filename);
}

视图按钮点击对应的前端代码如下:

function OnClickbtn() {
    $.ajax({
        type: "POST",
        url: vGenerateUrl,
        data: { },
        success: function(s) {
            DevExpress.ui.notify({ message: "xyz Generated", width: 1300 }, vSuccessMsgType, 3000);
        },
        error: function(result) {
            onAjaxError(result);
        }
    });
}

预期效果:点击按钮后后端生成.json文件,触发浏览器自动下载。实际测试时先后将接口返回类型修改为ActionResult、ContentResult、FileResult,均无法触发浏览器下载行为。

根本原因

浏览器仅会对直接导航、表单提交、用户主动触发的标签点击行为产生的文件流响应,自动触发下载弹窗。AJAX请求拿到的响应会直接交由JavaScript逻辑处理,无论后端返回头如何设置,浏览器都不会默认触发下载。

修复方案

后端代码优化

原后端代码存在冗余逻辑和潜在编码问题,调整后代码如下:

public FileResult GenerateJSON()
{
    string filename = "aa.json";
    // 用Path.Combine拼接路径,避免正反斜杠兼容问题
    string filepath = Path.Combine(VariableDeclarations.wwwPath, "Downloads", filename);
    // 直接读取文件字节数组,避免ReadAllText带来的编码不一致问题
    byte[] filedata = System.IO.File.ReadAllBytes(filepath);
    // 移除未使用的ContentDisposition对象声明、手动添加响应头的冗余代码
    // File方法传入第三个文件名参数时,框架会自动生成符合规范的Content-Disposition响应头
    return File(filedata, "application/json", filename);
}

前端代码调整

两种实现方案二选一即可:

  • 方案1(最简实现,无特殊鉴权/响应判断需求优先选):动态创建隐藏表单发起POST请求,浏览器识别到文件流响应后会自动触发下载,不会发生页面跳转
function OnClickbtn() {
    // 构建隐藏表单
    const downloadForm = document.createElement('form');
    downloadForm.method = 'POST';
    downloadForm.action = vGenerateUrl;
    // 有请求参数时,动态创建input节点插入表单即可传递
    document.body.appendChild(downloadForm);
    downloadForm.submit();
    document.body.removeChild(downloadForm);

    // 正常触发业务提示
    DevExpress.ui.notify({ message: "xyz Generated", width: 1300 }, vSuccessMsgType, 3000);
}
  • 方案2(需要保留AJAX逻辑做响应状态判断时使用):AJAX请求指定响应类型为二进制Blob,拿到响应后前端手动构建临时下载链接,模拟点击触发下载
function OnClickbtn() {
    $.ajax({
        type: "POST",
        url: vGenerateUrl,
        data: { },
        xhrFields: {
            responseType: 'blob' // 声明接收二进制响应
        },
        success: function(res) {
            // 生成Blob临时地址
            const blobUrl = window.URL.createObjectURL(new Blob([res], {type: 'application/json'}));
            // 创建临时a标签触发下载
            const tempLink = document.createElement('a');
            tempLink.href = blobUrl;
            tempLink.download = 'aa.json';
            document.body.appendChild(tempLink);
            tempLink.click();
            // 清理临时DOM和内存占用
            document.body.removeChild(tempLink);
            window.URL.revokeObjectURL(blobUrl);

            DevExpress.ui.notify({ message: "xyz Generated", width: 1300 }, vSuccessMsgType, 3000);
        },
        error: function(result) {
            onAjaxError(result);
        }
    });
}
注意事项
  • 无需手动给响应添加Content-Disposition头,File方法传入文件名参数后会自动生成标准头,手动重复添加反而可能导致响应头重复、浏览器解析失败。
  • 表单提交方式会自动携带当前站点的Cookie等鉴权信息,和普通AJAX请求的权限校验逻辑完全兼容。

内容的提问来源于stack exchange,提问作者Prathamesh Pitale

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:27:17