今天在用npoi導出xls時會報錯,經過在網上查找資料,找到一篇博客文章介紹的,原文地址
https://www.cnblogs.com/spring_wang/p/3160020.html
1.今天再處理Excel2007、2010文件,格式.xlsx文件存在一個問題,在調用 Write方法之后關閉了傳入的文件流。
2.今天針對此問題好一頓的測試:
2.1 在有文件構建時不是.xlsx文件格式會報錯,構建不成。.xls文件是不行的。
2.2 XSSFWorkbook對象調用 write方法傳去MemoryStream對象后,會自動關閉傳入的參數。導致往Response.OutputStream會有問題?
HSSFWorkbook對象則不會,針對這個問題還專門查了HSSFWorkbook源代碼下面有,本來想查XSSFWorkbook的源代碼,現在還沒公開呢。
3.再有導出.xlsx文件時,在打開時總報:
錯誤提示: Excel在“春天Excel2007.xlsx”中發現不可讀取內容。是否恢復工作簿的內容?如果信任此工作簿的來源,請單擊“是”。 單擊“是”后:Excel 已完成文件級驗證和修復。此工作簿的某些部分可能已被修復或丟棄。
那么這些問題如何處理呢?直接上代碼如下:
HSSFWorkbook類對象Write方法:
/// <summary> /// Write out this workbook to an Outputstream. Constructs /// a new POI POIFSFileSystem, passes in the workbook binary representation and /// Writes it out. /// </summary> /// <param name="stream">the java OutputStream you wish to Write the XLS to</param> public override void Write(Stream stream) { byte[] bytes = GetBytes(); POIFSFileSystem fs = new POIFSFileSystem(); // For tracking what we've written out, used if we're // going to be preserving nodes List<string> excepts = new List<string>(1); MemoryStream newMemoryStream = new MemoryStream(bytes); // Write out the Workbook stream fs.CreateDocument(newMemoryStream, "Workbook"); // Write out our HPFS properties, if we have them WriteProperties(fs, excepts); if (preserveNodes) { // Don't Write out the old Workbook, we'll be doing our new one excepts.Add("Workbook"); // If the file had WORKBOOK instead of Workbook, we'll Write it // out correctly shortly, so don't include the old one excepts.Add("WORKBOOK"); // Copy over all the other nodes to our new poifs CopyNodes(this.filesystem, fs, excepts); } fs.WriteFileSystem(stream); fs.Dispose(); newMemoryStream.Dispose(); bytes = null; }
問題2對應代碼:
FileStream fileStream = new FileStream(HttpContext.Current.Server.MapPath("~/Resources/Template/" + strHeaderText + ".xlsx"), FileMode.Create, FileAccess.Write); workbook.Write(fileStream);//調用這個后會關於文件流,在HSSFWorkbook不會關閉所以在處理時應注意 FileStream fs = new FileStream(HttpContext.Current.Server.MapPath("~/Resources/Template/" + strHeaderText + ".xlsx"), FileMode.Open, FileAccess.Read); long fileSize = fs.Length; byte[] fileBuffer = new byte[fileSize]; fs.Read(fileBuffer, 0, (int)fileSize); HttpContext.Current.Response.BinaryWrite(fileBuffer); fs.Close();
問題3對應代碼:
FileStream fileStream = new FileStream(HttpContext.Current.Server.MapPath("~/Resources/Template/" + strHeaderText + ".xlsx"), FileMode.Create, FileAccess.Write); workbook.Write(fileStream);//調用這個后會關於文件流,在HSSFWorkbook不會關閉所以在處理時應注意 FileStream fs = new FileStream(HttpContext.Current.Server.MapPath("~/Resources/Template/" + strHeaderText + ".xlsx"), FileMode.Open, FileAccess.Read); long fileSize = fs.Length; //加上設置大小下載下來的.xlsx文件打開時才沒有錯誤 HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString()); byte[] fileBuffer = new byte[fileSize]; fs.Read(fileBuffer, 0, (int)fileSize); HttpContext.Current.Response.BinaryWrite(fileBuffer); fs.Close();
結語:最后在本地正常,放服務器每次下載文件比實際要大,打開提示刪除不可見內容在最后加上一句正常
context.Response.Flush();