如何修复文件下载后冻结页面?(TreeView SelectedNodeChanged中的TransmitFile)

How to fix freezing page after file download?(TransmitFile in TreeView SelectedNodeChanged)

所以我知道这是一个常见问题,页面冻结(任何按钮在视觉上都是可点击的,但不执行任何操作)因为它在文件下载后没有关闭一些请求。

System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/txt";
response.AddHeader("Content-Disposition", "attachment; filename=" + TreeView1.SelectedNode.Text + ";");
response.TransmitFile(TreeView1.SelectedNode.Value);
response.Flush();
response.Close();
HttpContext.Current.ApplicationInstance.CompleteRequest();

此代码在 TreeView SelectedNodeChanged 事件中,这是一个问题。

例如,如果将传输代码放在某个按钮中,我可以通过向按钮添加 OnClientClick="javascript:setFormSubmitToFalse()" 来修复页面冻结,这个小 JavaScript 可以修复下载后的页面冻结问题。

<script type="text/javascript">
    //Fix page freeze after download dialog
    function setFormSubmitToFalse() {
        setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
        return true;
    }
</script>

但我不知道如何在单击 TreeView 节点时解决此问题。 TreeView 没有 OnClientClick,我也尝试 运行 传输代码 Page.ClientScript.RegisterStartupScript(this.GetType(), "CallMyFunction", "setFormSubmitToFalse()", true); 前后代码后面的 JS 函数,但它没有帮助,页面在文件后仍然冻结下载。

有什么办法可以解决这个问题吗?谢谢。

这是 Sharepoint 网站上的 Web 部件(几乎 asp.net 页)。

编辑:

我会尝试更好地解释我的情况以及我想要实现的目标。

所以我的主要目标是:在本地网络中有一个包含文档的共享文件夹,将要使用此应用程序的用户不应访问此共享文件夹,只有 运行ning 应用程序池的实体可以访问访问它。

我正在发出一些 SQL 请求,该请求为我提供了某个子文件夹的路径。我正在构建该子文件夹的树视图,当用户单击树视图 SelectedNodeChanged 事件快照中的某个文件时,我执行传输文件作为应用程序池标识

SPSecurity.RunWithElevatedPrivileges(delegate()
   {
   /* transmit file code */
   }); 

一切正常,但如果我理解正确,客户端可能会在 TransmitFile 发送后冻结页面并阻止向服务器发送任何其他 post 请求,这就是为什么我的小 JS 解决方案在执行 OnClientClick。

这是该修复程序的作者最初解释的方式,但我不知道如何将其实现到树视图中

我不确定我是否真的理解你的情况,但你的应用程序可能会被冻结,因为 UI 线程挂在你试图 运行 的代码上同步。

为了防止这种情况发生,您需要 运行 异步逻辑。

public async void OnSelectedNodeChanged(object sender, EventArgs e)
{
    await Task.Run(() => {
        System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
        response.ClearContent();
        response.Clear();
        response.ContentType = "text/txt";
        response.AddHeader("Content-Disposition", "attachment; filename=" + TreeView1.SelectedNode.Text + ";");
        response.TransmitFile(TreeView1.SelectedNode.Value);
        response.Flush();
        response.Close();
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }).ConfigureAwait(false);
}

这是一个异步 void 方法,这意味着触发此事件的代码 不会等待它完成,也不会 知道什么时候完成。

这将防止线程锁定您的 UI,但是如果用户能够通过单击您的 UI 周围的所有区域来 "rapid fire" 这些事件,则可能并不理想以这种方式编写代码。

无论如何,您可能需要一些形式的异步逻辑来完成您想要的。

所以解决方案非常简单,但有点棘手。

Nodes没有onClientClick事件,但是我们可以给任何页面元素添加JS点击事件,对吧?所以这是诀窍,当创建 TreeView 时,只需在 Span 的帮助下将点击添加到节点的实际文本:

...
TreeNode fileNode = new TreeNode
 {
     //before
     //Text = file.Name,
     //after
     Text = "<span onclick=\"javascript:setFormSubmitToFalse();\">"+file.Name+"</span>",
     Value = file.FullName,
 };
...

并且在传输节点的文件解析文本中具有文件的正常名称:

response.AddHeader("Content-Disposition", "attachment; filename=" + 
    TreeView1.SelectedNode.Text.Replace("<span onclick=\"javascript:setFormSubmitToFalse();\">", string.Empty).Replace("</span>", string.Empty) + ";");

现在一切正常,下载后页面不再冻结。