下载功能在 asp.net 的更新面板中不起作用

Posted

技术标签:

【中文标题】下载功能在 asp.net 的更新面板中不起作用【英文标题】:Download feature not working within update panel in asp.net 【发布时间】:2011-07-24 14:36:25 【问题描述】:

我有一个包含 FormView 的 Web 用户控件。 formview 显示求职者的详细信息。我为“下载简历”链接提供了一个按钮,以便管理员/HR 可以下载简历。我已将此控件放置在包含 UpdatePanel 的 aspx 页面中。除下载链接外,一切正常。

我已经给出了一个关于下载链接按钮的命令,并且一个函数与该命令相关联以开始下载。

下面是我实现的代码-

//Command on 'Download' link button within FormView
protected void lnkDownload_Command(object sender, CommandEventArgs e)

    if (e.CommandName.Equals("Download"))
    
        StartDownload(e.CommandArgument.ToString());
    


//My routine to download document
//sFileInfo contains filepath$==$mimetype
protected void StartDownload(string sFileInfo)

    string[] d = sFileInfo.ToString().Split((new string[]  "$==$" ), StringSplitOptions.None);
    string filename = d[0];
    string docType = d[1];

    System.IO.FileInfo file = new System.IO.FileInfo(d[0]);

    if (file.Exists)
    
        Response.Clear();
        Response.AddHeader("Content-Disposition", "attachment; filename=" + d[0]);
        Response.AddHeader("Content-Length", file.Length.ToString());
        Response.ContentType = d[1];
        Response.WriteFile(file.FullName);
        Response.End();
    
    else
    
        Server.Transfer("~/Mesgbox.aspx?cat=2");
    

如果更新面板被删除,代码可以完美运行,但如果使用更新面板,则会生成脚本错误。

有什么建议吗....?

感谢您分享您的时间。

【问题讨论】:

您是否在页面中添加了 asp:ScriptManager? 你找到解决这个问题的方法了吗? 【参考方案1】:

要启动整页回发,请将回发触发器添加到更新面板:

<asp:UpdatePanel runat="server">
    <Triggers>
        <asp:PostBackTrigger ControlID="YourControlID" />
    </Triggers>
    <ContentTemplate>
        .....

【讨论】:

以上问题是关于用户控制的,我在哪里可以添加触发器? 如果您尝试使用 Response 下载文件,这不会回答 @MichaelRudnerEvanchik - 它回答“下载功能在 asp.net 的更新面板中不起作用”键是 PostBackTrigger 而不是 AsyncPost .....谢谢 Mitul【参考方案2】:

您不能在 UpdatePanel 部分回发中返回附件,因为 ScriptManager 使用结果来更新 DIV(而不是整个响应)。最简单的解决方法是将下载按钮设置为回发控件。这将导致该按钮启动完整的回发。下面是要包含在 Page_Load 中的代码

ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(this.lnkDownload);

【讨论】:

我每次都忘记这一点 - 为将来参考添加书签...比尝试将我的所有 UpdatePanels 设为常规面板更好! 如果下载按钮在用户控件中,而UpdatePanel在其父页面中,那么这个解决方案肯定是合适的,因为注册可以在用户控件的page_load事件中完成。【参考方案3】:

您仍然可以从更新面板中触发下载文档。

我有一个更新面板,里面有 3 个嵌套中继器。在最内部的中继器中,我使用 LinkBut​​tons 构建了一系列下载链接,每个链接都包含一个命令,用于通过 web 服务获取文档并分派它。

每个转发器都有一个 OnItemDataBound 方法。在最后一个中继器中,我有以下

        protected void LinkDocRepeaterOnItemDataBound(object sender, RepeaterItemEventArgs e) 
            if(!(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)) 
            return;
                
            LinkButton linkButton = (LinkButton)e.Item.FindControlRecursive("LinkId");
            var scriptManager = ScriptManager.GetCurrent(this.Page);
            if (scriptManager != null) 
               scriptManager.RegisterPostBackControl(linkButton);
            
        

现在每个链接按钮都会下载一个文档。

【讨论】:

【参考方案4】:

我的情况:

我有一个从 sql 数据加载的长时间运行的 excel 文件,我希望更新进度面板在创建文件时显示微调器 gif,然后从更新面板中下载文件。这比我想象的要复杂。

这个链接在搜索中的排名很高,在试图避免它之后,结果发现 iframe 对我很有用。

iframe async download

这是最终的工作..(这个确切的代码尚未经过测试)

MyPage.aspx...(在更新面板内,无触发器)

<asp:Button runat="server" ID="btnExcelExport" Text="Export to Excel" OnClick="btnExcelExport_Click" />

<iframe runat="server" id="ifmExcel"   margin margin
                    frameborder="0" />

MyPage.aspx.cs

        protected void btnExcelExport_Click(object sender, EventArgs e)
        
            //long running process here, taking advantage of the update progress panel
            var bytes = GetExcelFile();
            //generate a key to pass to the download page to access the file bytes
            var cacheKey = Guid.NewGuid().ToString("N");//N means no hyphens
            //placing the result in cache for a few seconds so the download page can grab it             
            Context.Cache.Insert(key: cacheKey, value: bytes, dependencies: null, absoluteExpiration: DateTime.Now.AddSeconds(30), slidingExpiration: System.Web.Caching.Cache.NoSlidingExpiration);
            ifmExcel.Attributes.Add("src", String.Format("MyDownloadPage.aspx?cacheKey=0", cacheKey));
        

MyDownloadPage.aspx.cs...

        protected void Page_Load(object sender, EventArgs e)
    
        if (!IsPostBack)
        
            var bytes = Context.Cache.Get(Request.QueryString.Get("cacheKey")) as byte[];
            Response.Clear();
            Response.AddHeader(
                "content-disposition", string.Format("attachment; filename=0.xlsx", "Invoice"));
            Response.ContentType = "application/xlsx";
            Response.BinaryWrite(bytes);
            Response.End();
        
    

它似乎像任何其他异步回发一样按预期工作。

【讨论】:

【参考方案5】:

ASPX 标记:

 <asp:UpdatePanel ID="UpdatePanel5" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:GridView ID="gv_Files" runat="server" AllowPaging="True" PageSize="7" OnPageIndexChanging="gv_Files_PageIndexChanging" AutoGenerateColumns="false" EmptyDataText="No files uploaded" GridLines="None">
            <Columns>
                <asp:BoundField DataField="Filename" HeaderText="File Name"  ItemStyle-CssClass="Files_css"  />
                <asp:BoundField DataField="DateCreated" HeaderText="Upload Date" ItemStyle-CssClass="Files_css"  />
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:LinkButton ID="lnkDownload" Text="Download" CausesValidation="false" CommandArgument='<%# Eval("FileName_Guid")+  ";" + Eval("Filename")  %>' runat="server" OnClick="DownloadFile"></asp:LinkButton>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:LinkButton ID="lnkDelete" Text="Del" CausesValidation="false" CommandArgument='<%# Eval("FileName_Guid")+ ";" + Eval("File_ID")+ ";" + Eval("Filename") + ";" + Eval("Platform_Config_ID") %>' runat="server" OnClick="DeleteFile" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </ContentTemplate>
    <Triggers>
        <%--<asp:AsyncPostBackTrigger ControlID="gv_Files" />--%>                   
    </Triggers>
</asp:UpdatePanel>

后面的代码:

    protected void UploadFile(object sender, EventArgs e)
    
        if (FileUpload1.HasFile)
        
            string FileName = Path.GetFileName(FileUpload1.PostedFile.FileName);
            string extension = "." + FileName.Split('.')[1].ToString();
            string FileName_Guid = Convert.ToString(Guid.NewGuid()) + extension;
            FileUpload1.PostedFile.SaveAs(@"C:\Uploads\" + FileName_Guid);
            string Platform_Config_ID = PlatformConfigID.Value;
            DataTable dt = new DataTable();
            dt = DAL.Upload_File(FileName_Guid, FileName, Platform_Config_ID);

            gv_Files.DataSource = dt;
            gv_Files.DataBind();
            ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
            scriptManager.RegisterPostBackControl(gv_Files);
        
    

    protected void DownloadFile(object sender, EventArgs e)
    
        try
                        
            LinkButton lnkDownload = (LinkButton)sender;
            GridViewRow row = (GridViewRow)lnkDownload.NamingContainer;
            LinkButton download = row.FindControl("lnkDownload") as LinkButton;
            ScriptManager.GetCurrent(this).RegisterPostBackControl(download);
            string FileName = (sender as LinkButton).CommandArgument.Split(';')[0].ToString();
            string OriginalFileName = (sender as LinkButton).CommandArgument.Split(';')[1].ToString();
            string FilePath = @"C:\Uploads\" + FileName.ToString();
            FileInfo file = new FileInfo(FilePath);
            if (file.Exists)
                                
                Response.ContentType = ContentType;
                Response.AppendHeader("Content-Disposition", "attachment; filename=" + OriginalFileName);
                Response.Headers.Set("Cache-Control", "private, max-age=0");
                Response.WriteFile(FilePath);                    
                Response.End();                                     
                            
        
        catch (Exception ex)
        
            // do nothing
        
    


    protected void DeleteFile(object sender, EventArgs e)
    
        string FileName_Guid = (sender as LinkButton).CommandArgument.Split(';')[0].ToString();
        string File_ID = (sender as LinkButton).CommandArgument.Split(';')[1].ToString();
        string Filename = (sender as LinkButton).CommandArgument.Split(';')[2].ToString();
        string Platform_Config_ID = (sender as LinkButton).CommandArgument.Split(';')[3].ToString();
        string FilePath = @"C:\Uploads\" + FileName_Guid;
        File.Delete(FilePath);

        DataTable dt = new DataTable();
        dt = DAL.Delete_File(File_ID, Filename, Platform_Config_ID);

        gv_Files.DataSource = dt;
        gv_Files.DataBind();
    

【讨论】:

第 1 步: 确保更新面板模式设置如下:UpdateMode="Conditional",然后按照我上面在后面的代码中显示的步骤进行操作。您必须在代码隐藏中将控件注册为回发控件。它就像一个魅力!【参考方案6】:

您不能在更新面板中使用 Response 对象。

【讨论】:

这就是我的问题。 Response.WriteFile() 正在生成错误。有什么解决办法吗?【参考方案7】:

请尝试以下步骤:

     

    <asp:UpdatePanel ID="UpdatePanel5" runat="server" l**UpdateMode="Conditional"**>
    <asp:GridView ID="gv_Files" runat="server" AllowPaging="True" PageSize="7" OnPageIndexChanging="gv_Files_PageIndexChanging" AutoGenerateColumns="false" EmptyDataText="No files uploaded" GridLines="None">
    

    (代码隐藏)UploadFile()

    ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
    scriptManager.RegisterPostBackControl(gv_Files);
    

    DownloadFile()

    DownloadFile() --> LinkButton download = row.FindControl("lnkDownload") as LinkButton;
    ScriptManager.GetCurrent(this).RegisterPostBackControl(download);
    

【讨论】:

以上是关于下载功能在 asp.net 的更新面板中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 警报在 asp.net 的更新面板中不起作用

回发后,我的 JavaScript 函数在 ASP.NET 中不起作用

下拉列表在 asp.net 的移动视图中不起作用

必需属性在 ASP.NET 中不起作用

数据注释在部分 ASP.NET MVC 中不起作用 jquery 不显眼的验证

更新面板中的 ASP.NET 按钮问题