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

ASP.NET文件下载完成后JavaScript加载器无法隐藏问题

问题原因

当触发文件下载时,后端执行Response.End()会立即终止HTTP响应,后续注册的HideLoader()脚本根本不会被发送到客户端;同时文件下载是独立的响应流,不会触发页面刷新,即使没有Response.End(),后端注册的脚本也无法在当前页面执行,导致加载器一直显示。


解决方案1:AJAX+Blob异步下载(推荐)

将同步提交改为AJAX请求,后端返回文件字节流,前端通过Blob创建下载链接,全程可控加载器显示隐藏。

前端代码修改

<div id="ContentPlaceHolder1_divShowLoadingGif" class="dvLoader" style="display: none;"> 
    <img id="img2" alt="" src="images/1487.png" />
</div>

<button id="ContentPlaceHolder1_btnDownloadInfo" class="btn btn-primary downnloadReport">Report Download</button>

<script>
function showloadingGif_UPLOAD() {
    document.getElementById('ContentPlaceHolder1_divShowLoadingGif').style.display = 'inline';
}

function HideLoader() {
    document.getElementById('ContentPlaceHolder1_divShowLoadingGif').style.display = 'none';
}

// 绑定按钮点击事件
document.getElementById('ContentPlaceHolder1_btnDownloadInfo').addEventListener('click', function() {
    showloadingGif_UPLOAD();
    const dateFilter = document.getElementById('<%= txtDateSelection.ClientID %>').value;
    
    fetch('<%= ResolveUrl("~/YourPage.aspx/DownloadReportAsync") %>', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json; charset=utf-8'
        },
        body: JSON.stringify({ strDateFilter: dateFilter })
    })
    .then(response => {
        if (!response.ok) throw new Error('请求失败');
        return response.blob();
    })
    .then(blob => {
        // 创建并触发下载链接
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `JIO_LOS_REPORT_${new Date().toString()}.xlsx`;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    })
    .catch(err => {
        alert('下载失败:' + err.message);
    })
    .finally(() => {
        // 无论成功失败都隐藏加载器
        HideLoader();
    });
});
</script>

后端新增异步Web方法

[WebMethod]
public static byte[] DownloadReportAsync(string strDateFilter)
{
    DataTable dtExcelData = new DataTable();
    try
    {
        CommonUser ObjUser = new CommonUser();
        dtExcelData = ObjUser.GET_EXCEL_REPORT(strDateFilter);

        if (dtExcelData == null || dtExcelData.Rows.Count == 0)
        {
            throw new Exception("No record found");
        }

        using (XLWorkbook wb = new XLWorkbook())
        {
            wb.Worksheets.Add(dtExcelData, "SheetName");
            using (MemoryStream ms = new MemoryStream())
            {
                wb.SaveAs(ms);
                return ms.ToArray();
            }
        }
    }
    catch (Exception ex)
    {
        string strErrorMsg = ex.Message.ToString() + " " + "StackTrace :" + ex.StackTrace.ToString();
        CommonDB.WriteLog("ERROR:" + strErrorMsg, ConfigurationManager.AppSettings["AIRFIBER_LOG"].ToString());
        throw ex;
    }
}

解决方案2:Cookie检测加载器隐藏

如果不想修改为AJAX,可在后端下载完成后设置Cookie,前端定时检测Cookie状态来隐藏加载器。

后端DownloadReport方法修改

public static void DownloadReport(DataTable dtRecord)
{
    try
    {
        string strFilename = string.Empty;
        
        using (XLWorkbook wb = new XLWorkbook())
        {
            wb.Worksheets.Add(dtRecord, "SheetName");
            strFilename = DateTime.Now.ToString();

            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.Buffer = true;
            HttpContext.Current.Response.Charset = "";
            HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            
            HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=JIO_LOS_REPORT_"+ strFilename +".xlsx");
            
            // 设置下载完成标识Cookie
            HttpContext.Current.Response.Cookies.Add(new HttpCookie("DownloadComplete", "true") { Expires = DateTime.Now.AddMinutes(1) });
            
            using (MemoryStream MyMemoryStream = new MemoryStream())
            {
                wb.SaveAs(MyMemoryStream);
                MyMemoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
                HttpContext.Current.Response.Flush();
                // 用Close替代End,避免终止响应导致Cookie无法写入
                HttpContext.Current.Response.Close();                     
            }
        }
    }
    catch (Exception ex)
    {   
        string strErrorMsg = ex.Message.ToString() + " " + "StackTrace :" + ex.StackTrace.ToString();
        CommonDB.WriteLog("ERROR:" + strErrorMsg, ConfigurationManager.AppSettings["AIRFIBER_LOG"].ToString());
    }
}

前端新增检测脚本

<script>
function showloadingGif_UPLOAD() {
    document.getElementById('ContentPlaceHolder1_divShowLoadingGif').style.display = 'inline';
    // 启动定时检测
    checkDownloadComplete();
}

function HideLoader() {
    document.getElementById('ContentPlaceHolder1_divShowLoadingGif').style.display = 'none';
}

function checkDownloadComplete() {
    const interval = setInterval(() => {
        const cookie = document.cookie.split('; ').find(row => row.startsWith('DownloadComplete='));
        if (cookie) {
            HideLoader();
            // 清除Cookie
            document.cookie = "DownloadComplete=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
            clearInterval(interval);
        }
    }, 500);
}
</script>

关键注意点

  • 禁止使用Response.End():它会强制终止HTTP响应,导致后续Cookie、脚本无法发送,改用Response.Close()或HttpContext.Current.ApplicationInstance.CompleteRequest()。
  • 同步下载场景下,页面不会刷新,后端注册的脚本无法执行,必须通过前端主动检测(Cookie/AJAX回调)控制加载器状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 12:45:55