使用WordprocessingDocument错误:无法创建互斥锁

时间:2015-02-23 11:45:24

标签: c# .net openxml docx openxml-sdk

我使用这个简单的模式在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的100,000条记录。

在当地,它运作得很好;在生产服务器(赢得2012 R2)中,它适用于小文件;但是在大文件中(当写入文件的记录太多时)我收到此错误:

  

无法创建互斥锁。 (HRESULT异常:0x80131464)

这是堆栈跟踪:

  

at System.IO.IsolatedStorage.IsolatedStorageFile.Open(String infoFile,String syncName)      在System.IO.IsolatedStorage.IsolatedStorageFile.Lock(布尔和锁定)      在System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享,Int32 bufferSize,IsolatedStorageFile isf)      在MS.Internal.IO.Packaging.PackagingUtilities.SafeIsolatedStorageFileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享,ReliableIsolatedStorageFileFolder文件夹)      在MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32 retryCount,String& fileName)      在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计数)      at MS.Internal.IO.Zip.ProgressiveCrcCalculatingStream.Write(Byte [] buffer,Int32 offset,Int32 count)      在MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Write(Byte []缓冲区,Int32偏移量,Int32计数)      在System.Xml.XmlUtf8RawTextWriter.FlushBuffer()      在System.Xml.XmlUtf8RawTextWriter.RawText(Char * pSrcBegin,Char * pSrcEnd)      在System.Xml.XmlUtf8RawTextWriter.RawText(String s)      at System.Xml.XmlUtf8RawTextWriter.WriteStartAttribute(String prefix,String localName,String ns)      at System.Xml.XmlWellFormedWriter.WriteStartAttribute(String prefix,String localName,String 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?我该如何防止这种情况?

1 个答案:

答案 0 :(得分:2)

在堆栈跟踪中,您可以找到SparseMemoryStream类。引擎盖下的这个类使用Memory Stream或Isolated Storage。它取决于2个参数,称为低水位标记高水位标记。如果内存消耗>比高水位标记然后使用隔离存储。正如您所观察到的那样,在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库的作者有类似的problem,在我看来,解决方案是使用非Microsoft打包库。

我不知道openxml-sdk但也许可以用其他东西替换默认的Microsoft打包解决方案。