GridView UpdatePanel RowCommand 实现下载文件
<div> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> </div> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:GridView ID="GridView1" runat="server" Width="100%" Font-Size="Small" PageSize="8> <Columns> <asp:TemplateField> <ItemTemplate> <asp:ImageButton ID="comfirmbtn" runat="server" ImageUrl="images/dataCorrection.png" ToolTip="生成确认单" CommandName="confirm" CommandArgument='<%#Eval("PSCode")+"*"+Eval("PSName")%>' OnInit="ImgBtnInit"></asp:ImageButton> </ItemTemplate> </asp:TemplateField> ......................... </Columns> </asp:GridView> </ContentTemplate> </asp:UpdatePanel>
问题:由于UpdatePanel的影响,导致在页面中点击ImageButton时会提示下面所示的错误,不会弹出所期望的下载页面 。
解决方法:在ImageButton的OnInit事件中用一下scriptManager的RegesterPostBcakControl((Control)sender)方法。
后台:
protected void ImgBtnInit(object sender, EventArgs e) { ScriptManager1.RegisterPostBackControl((Control)sender); }
由于在updatepanel中无法使用Response.Write(...),所以如果在UpdatePanel内的按钮的事件响应代码中含有Response.Write(...)就会出错,具体什么原因我不知道;
解决的办法是,在updatepanel的trigger中将该按钮添加为PostbackTrigger。之后该按钮的事件响应函数就可以使用Response.Write()了。
如果我的按钮不是独立存在的,而是gridview的一个模板字段内的按钮,那么在添加的时候只能将整个gridview作为postback的trigger,那将会殃及gridview其他无刷新的功能,解决办法,只要在那个模板字段内控件的init事件中用一下scriptManager的RegesterPostBcakControl((Control)sender);就可以了
实例演示:
前台:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"></asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:GridView ID="gvData" runat="server" AutoGenerateColumns="False" DataKeyNames="RoleName,RoleId,ColumnId" EmptyDataText="未找到信息" CellPadding="4" SkinID="gridviewSkin1" Style="width: 650px;" OnRowCancelingEdit="gvData_RowCancelingEdit" OnRowEditing="gvData_RowEditing" OnRowUpdating="gvData_RowUpdating" OnRowDataBound="gvData_RowDataBound" OnRowCommand="gvData_RowCommand"> <Columns> <asp:TemplateField HeaderText="操作"> <asp:LinkButton ID="lnkbtn_ExportAuthority" runat="server" CommandArgument="<%# ((GridViewRow)Container).RowIndex %>" CommandName="ExportAuthority" OnInit="lnkbtn_ExportAuthority_Init">导出权限</asp:LinkButton> </asp:TemplateField> </Columns> </asp:GridView> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnSearch" EventName="Click" /> <%--<asp:AsyncPostBackTrigger ControlID="gvData" /> 这里不需要--%> </Triggers> </asp:UpdatePanel>
后台:
protected void gvData_RowCommand(object sender, GridViewCommandEventArgs e) { //导出权限 if (e.CommandName == "ExportAuthority") { int _index = Convert.ToInt32(e.CommandArgument); Guid _appId = new Guid(this.hid_AppId.Value); Guid _roleId = new Guid(gvData.DataKeys[_index][1].ToString()); int _columnId = int.Parse(gvData.DataKeys[_index][2].ToString()); string _fileName = string.Format("{0}-{1}-角色权限数据-{2}.txt", ((Label)gvData.Rows[_index].FindControl("lblArea")).Text, ((Label)gvData.Rows[_index].FindControl("lbl_description")).Text, DateTime.Now.ToString("yyyyMMdd")); ExportAuthority(_appId, _roleId, _columnId, _fileName); } } //导出权限 private void ExportAuthority(Guid appId, Guid roleId, int columnId, string fileName) { try { string _roleAuthority = "", _result = ""; BLL.aspnet_RolesAuthority bll_RoleAuthority = new BLL.aspnet_RolesAuthority(); Model.aspnet_RolesAuthority model_RoleAuthority = new Model.aspnet_RolesAuthority(); model_RoleAuthority = bll_RoleAuthority.GetModel(appId, roleId, columnId); if (!object.Equals(model_RoleAuthority, null)) { _roleAuthority = model_RoleAuthority.ModuleStr; } _result = DESEncrypt.Encrypt(_roleAuthority); //保存文档,并下载 string _folderName = "/temp/"; string _serverFolderName = Server.MapPath(_folderName);//临时文件夹名 Random r = new Random(); string _fileName = fileName;// DateTime.Now.ToString("yyyyMMddHHmmss") + r.Next(1000, 9999) + "-RoleAuthority-export.txt";//文件名 string _tempFilePath = _serverFolderName + _fileName;//完整的文件路径 if (!Directory.Exists(_serverFolderName)) { //创建临时目录 Directory.CreateDirectory(_serverFolderName); } //保存生成的文档 FileStream fs1 = new FileStream(_tempFilePath, FileMode.Create, FileAccess.Write);//创建写入文件 StreamWriter sw = new StreamWriter(fs1); sw.WriteLine(_result);//开始写入值 sw.Close(); fs1.Close(); //方法一: ////以字符流的形式下载文件 //FileStream fs = new FileStream(_tempFilePath, FileMode.Open); //byte[] bytes = new byte[(int)fs.Length]; //fs.Read(bytes, 0, bytes.Length); //fs.Close(); //HttpContext.Current.Response.ContentType = "application/octet-stream"; ////通知浏览器下载文件而不是打开 //HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(_fileName, System.Text.Encoding.UTF8)); //HttpContext.Current.Response.BinaryWrite(bytes); //HttpContext.Current.Response.Flush(); //HttpContext.Current.Response.End(); //方法二: FileInfo fileInfo = new FileInfo(_tempFilePath); Response.Clear(); Response.ClearContent(); Response.ClearHeaders(); //添加头信息,为"文件下载/另存为"对话框指定默认文件名,设定编码为UTF8,防止中文文件名出现乱码 //把attachment改为online 则表示在线查看 Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(_fileName, System.Text.Encoding.UTF8)); //添加头信息,指定文件大小,让浏览器能够显示下载进度 Response.AddHeader("Content-Length", fileInfo.Length.ToString()); Response.AddHeader("Content-Transfer-Encoding", "binary"); //指定返回的是一个不能被客户端读取的流,必须被下载 Response.ContentType = "application/octet-stream"; Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8"); // 把文件流发送到客户端 Response.WriteFile(fileInfo.FullName); Response.Flush(); Response.End(); } catch (Exception ex) { System.Web.UI.ScriptManager.RegisterStartupScript(this.UpdatePanel1, this.GetType(), "MyScript", string.Format("alert(\"错误:{0}\");", ex.Message), true); } } //这里是关键,不然不会弹出下载文件的提示框 protected void lnkbtn_ExportAuthority_Init(object sender, EventArgs e) { ScriptManager1.RegisterPostBackControl((Control)sender); }