我使用这个简单的模式在ASP.NET应用程序中创建一个docx文件:
var outputFileName = "creating some file name here...";
var outputFile = string.Format("~/App_Data/files/{0}.docx", outputFileName);
// creating a file stream to write to
var outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputFile), FileMode.OpenOrCreate);
// creating the default template
using (var sr = new StreamReader(HttpContext.Current.Server.MapPath("~/some-template.docx"), Encoding.UTF8)) {
var l = (int)sr.BaseStream.Length;
var buffer = new byte[l];
sr.BaseStream.Read(buffer, 0, l);
outputStream.Write(buffer, 0, l);
}
// creating the document parts
using (WordprocessingDocument docx = WordprocessingDocument.Open(outputStream, true)) {
// adding parts here...
// adding a large amount of data in an iterator
foreach(var item in someList) {
// adding some parts...
outputStream.Flush();
}
docx.Close();
}
outputStream.Flush();
outputStream.Close();
outputStream.Dispose();
我不得不说,我正在处理的数据大约是来自DB的100000条记录。
在当地,它运行得很好;在生产服务器(win2012R2)中,它可以很好地处理小文件;但在大文件中(当有太多的记录要写入文件时),我会得到这个错误:
无法创建互斥对象。(HRESULT异常:0x80131464)
这是堆栈跟踪:
位于System.IO.IsolatedStorage.IsolatedStorage File.Open(字符串信息文件,字符串同步名称)位于System.IO.IsolatedStorage.IsolatedStorage File.Lock(布尔值和锁定值)位于System.IO.IsolatedStorage.IsolatedStorage FileStream.ctor(字符串路径、文件模式、文件访问、文件共享、Int32缓冲区大小、IsolatedStorageFile isf)位于MS.Internal.IO.Packaging.PackagingUtilities.SafeIsolatedStorageFileStream.ctor(字符串路径、FileMode模式、FileAccess访问、FileShare共享、ReliableIsolatedSorageFileFolder文件夹)位于MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32重试计数,字符串和文件名)位于MS.Internal.IO.Packaging。SparseMemoryStream。SwitchModeIfNecessary()在MS.Internal.IO.Packaging.SparseMemoryStream.Write(Byte[]缓冲区,Int32偏移量,Int32计数)位于MS.Internal.IO.Packaging.CompressEmulationStream.Write(Byte[]缓冲区,Int32偏移量,Int32计数)在MS.Internal.IO.Packaging.CompressStream.Write(Byte[]缓冲区,Int32偏移量,Int32计数)在MS.Internal.IO.Zip.ProgressiveCrcCalculatingStream.Write(Byte[]缓冲区,Int32偏移量,Int32计数)在MS.Internal.IO.ZipZipIOModeEnforceingStream.Write(Byte[]缓冲区,Int32偏移量,Int32计数)位于System.Xml.XmlUtf8RawTextWriter.FlushBuffer()位于System.Xml.XmlUtf8RawTextWriter.RawText(Char*pSrcBegin,Char*pSrc End)位于System.Xml.XmlUtf8RawTextWriter.RawText(字符串s)位于System.Xml.XmlUtf8RawTextWriter.WriteStartAttribute(字符串前缀、字符串localName、字符串ns)位于System.Xml.XmlWellFormedWriter.WriteStartAttribute(字符串前缀、字符串localName、字符串namespaceName)位于DocumentFormat.OpenXml.OpenXmlElement.WriteAttributesTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w)位于DocumentFormat.OpenXml.OpenXmlPartRootElement.WriteTo(XmlWriter XmlWriter)位于DocumentFormat.OpenXml.OpenXmlPartRootElement.SaveToPart(OpenXmlPart OpenXmlPart)位于DocumentFormat.OpenXml.OpenXmlPartRootElement.Save()位于DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SavePartContents()位于DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose(布尔处理)位于DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose()在MyClass.GetDocx()
问题是:当我将文件写入自己的App_Data
文件夹时,为什么要写入IsolatedStorage
?我该如何防止这种情况发生?
在堆栈跟踪中,您可以找到SparseMemoryStream类。此类在后台使用内存流或隔离存储。它取决于两个名为低水位线和高水位线的参数。如果内存消耗量大于高水位线,则使用隔离存储。正如您所观察到的,在IIS上运行服务器端应用程序的情况下,这会成为一个问题。不幸的是,问题是这些参数的值在CompressStream类中是硬编码的。换句话说,它是经过设计的。
private const long _lowWaterMark = 0x19000; // we definately would like to keep everythuing under 100 KB in memory
private const long _highWaterMark = 0xA00000; // we would like to keep everything over 10 MB on disk
EPPlus库的作者也遇到了类似的问题,在我看来,解决方案是使用非Microsoft打包库。
我不知道openxml-sdk,但也许可以用其他东西替换默认的Microsoft打包解决方案。