前段时间做了一个Export 数据到Excel的功能。数据存储在Tree View中,父子关系明确。要求在Excel中也要明确父子关系。不可避免的,需要在后台先分析TreeView中的父子关系然后再生成Excel,耗费时间。只要数据量稍微大些,父子关系复杂些,下载Excel就会很慢,而且下载不成功。原因?Rquest在等待较长时间后自动关闭了。
解决的方法就是将Request header中的Connection 属性设置为Keep-alive的。
关于下载部分,我写了两种方法,效果感觉差不多。
1。应用Response.WriteFile
1 private void CreateExcel() 2 { 3 string windowsTempDirPath = Utility.GetWindowsTempDirConfigKey(); 4 string localPath = windowsTempDirPath + "GeneratedTemplate.xlsx"; 5 6 File.Copy(Server.MapPath("~/Templates/ExcelTemplate.xlsx"), localPath, true); 7 8 using (SpreadsheetDocument myWorkbook = SpreadsheetDocument.Open(localPath, true)) 9 { 10 this.workbookPart = myWorkbook.WorkbookPart; 11 this.workbookPart.WorkbookStylesPart.Stylesheet = Utility.CreateStylesheet(); 12 this.worksheetPart = workbookPart.WorksheetParts.First(); 13 this.sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>(); 14 15 Row headerRow = CreateHeaderRow(); 16 this.sheetData.AppendChild(headerRow); 17 18 var tempTree = new TreeView(); 19 TreeNode rootNode = this.CreateRootNode( 20 this.GrpDisplayName.Value, 21 this.GrpDomain.Value, 22 this.GrpGuid.Value, 23 this.GrpAlias.Value, 24 this.GrpType.Value); 25 tempTree.Nodes.Add(rootNode); 26 this.GroupMembershipItems = HttpContext.Current.Session["GroupMembershipItems"] as List<GroupMembershipItem>; 27 this.PrepareTreeView(tempTree, rootNode, false); 28 this.AddTreeNodeDataToExcel(tempTree.Nodes); 29 } 30 //download excel 31 HttpContext.Current.Response.ClearContent(); 32 HttpContext.Current.Response.ClearHeaders(); 33 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=GroupMembershipReport.xlsx"); 34 HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument." + "spreadsheetml.sheet"; 35 FileStream fis = null; 36 try 37 { 38 fis = File.OpenRead(localPath); 39 long dataToRead = fis.Length; 40 HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString()); 41 //keep connection alive 42 Response.AddHeader("Connection", "Keep-Alive"); 43 Response.ContentEncoding = System.Text.Encoding.UTF8; 44 45 Response.WriteFile(localPath); 46 Response.Flush(); 47 Response.Close(); 48 System.IO.File.Delete(localPath); 49 } 50 finally 51 { 52 if (fis != null) 53 { 54 fis.Close(); 55 } 56 Response.Flush(); 57 Response.Close(); 58 } 59 }
2. 使用Response.OutputStream.Write
1 private void CreateExcel() 2 { 3 string windowsTempDirPath = Utility.GetWindowsTempDirConfigKey(); 4 string localPath = windowsTempDirPath + "GeneratedTemplate.xlsx"; 5 6 File.Copy(Server.MapPath("~/Templates/ExcelTemplate.xlsx"), localPath, true); 7 8 using (SpreadsheetDocument myWorkbook = SpreadsheetDocument.Open(localPath, true)) 9 { 10 this.workbookPart = myWorkbook.WorkbookPart; 11 this.workbookPart.WorkbookStylesPart.Stylesheet = Utility.CreateStylesheet(); 12 this.worksheetPart = workbookPart.WorksheetParts.First(); 13 this.sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>(); 14 15 Row headerRow = CreateHeaderRow(); 16 this.sheetData.AppendChild(headerRow); 17 18 var tempTree = new TreeView(); 19 TreeNode rootNode = this.CreateRootNode( 20 this.GrpDisplayName.Value, 21 this.GrpDomain.Value, 22 this.GrpGuid.Value, 23 this.GrpAlias.Value, 24 this.GrpType.Value); 25 tempTree.Nodes.Add(rootNode); 26 this.GroupMembershipItems = HttpContext.Current.Session["GroupMembershipItems"] as List<GroupMembershipItem>; 27 this.PrepareTreeView(tempTree, rootNode, false); 28 this.AddTreeNodeDataToExcel(tempTree.Nodes); 29 } 30 31 HttpContext.Current.Response.ClearContent(); 32 HttpContext.Current.Response.ClearHeaders(); 33 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=GroupMembershipReport.xlsx"); 34 HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument." + "spreadsheetml.sheet"; 35 FileStream fis = null; 36 try 37 { 38 fis = File.OpenRead(localPath); 39 long dataToRead = fis.Length; 40 int readLength = 0; 41 byte[] buffer = new byte[1000]; 42 43 HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString()); 44 Response.AddHeader("Connection", "Keep-Alive"); 45 Response.ContentEncoding = System.Text.Encoding.UTF8; 46 while (dataToRead > 0) 47 { 48 if (Response.IsClientConnected) 49 { 50 readLength = fis.Read(buffer, 0, 1000); 51 Response.OutputStream.Write(buffer, 0, readLength); 52 Response.Flush(); 53 buffer = new byte[1000]; 54 dataToRead = dataToRead - readLength; 55 } 56 else 57 { 58 dataToRead = -1; 59 Logger.Write("client is not connected", "client"); 60 } 61 } 62 } 63 catch (Exception e) 64 { 65 throw e; 66 } 67 finally 68 { 69 if (fis != null) 70 { 71 fis.Close(); 72 } 73 Response.Flush(); 74 Response.Close(); 75 } 76 //Response.WriteFile(localPath); 77 //Response.Flush(); 78 //Response.Close(); 79 System.IO.File.Delete(localPath); 80 }
下面是下载文件时使用IE Developer Tool获取到的Request Header和Response Header。当遭遇到Http Network等不好捕捉的问题时,这个Developer Tool会帮上大忙的。