简体   繁体   中英

Download feature not working within update panel in asp.net

I have a Web User Control containing a FormView . The formview shows details of job seeker. I have provided a button for "Download Resume" link, so that admin/HR can download the resume. I have placed this control in an aspx page that contains the UpdatePanel. Everything works fine except Download Link.

I have given a Command on donwload link button and a function is associated with the command to start download.

Below is the code i have implemented -

//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");
    }
}

The code works perfectly if update panel is removed but generates script errors if update panel is used.

Any suggestions....?

Thanks for sharing your time.

To initiate a full page postback, you add a postback trigger to your update panel:

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

You cannot return an attachment in an UpdatePanel partial postback, since the results are used by the ScriptManager to update a DIV (not the whole response). The simplest fix for what you're trying to do would be to make your download button as a postback control. That would cause that button to initiate a full postback. Here's the code below to include in your Page_Load

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

You can still trigger download doc from inside an Update Panel.

I have an update panel and inside I have 3 nested repeaters. In the most inner repeater I build a series of download links using LinkButtons, each one containing a command to fetch the document via webservice and dispatching it.

Each repeater has an OnItemDataBound method. In the last repeater I have the following

        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);
            }
        }

Each Linkbutton now downloads a document.

My situation:

I had a long running excel file loaded from sql data and I wanted update progress panel to display the spinner gif while the file was created and then download the file from within the update panel. It was trickier than I thought.

This link came up high on searches and after trying to avoid it, it turned out that an iframe was useful to me.

iframe async download

Here is what ended up working.. (this exact code has not been tested)

MyPage.aspx...(inside update panel, no triggers)

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

<iframe runat="server" id="ifmExcel" width="0" height="0" marginheight="0" marginwidth="0"
                    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();
        }
    }

It seems to work as expected like any other async post back would.

ASPX markup:

 <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>

Code behind:

    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();
    }

Please try the following steps:

  1.  <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">
  2. (Code Behind) UploadFile()

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM