首页 > 解决方案 > 流未打开以供阅读

问题描述

我正在从 Cloud 下载 PowerPoint 文件。为了限制下载文件的多次调用,我使用MemoryCache. 下面的代码在第一次运行时运行良好,但在第一次运行后会抛出异常:

“未打开该流以供阅读。”

下面是我正在使用的代码:

var cache = MemoryCache.Default;
var memoryStream = new MemoryStream();
if(cache.contains(key)) {
    memoryStream = (MemoryStream)cache.Get(key);
} else {
    var file = getFile();
    cache.Add(key, file);
    memoryStream = (MemoryStream)cache.Get(key);
}

using(memoryStream) {
    Open file and do manupulation then save the file in cloud.
}

更新代码:

var cache = MemoryCache.Default;
byte[] data = (byte[])cache.Get(key);
if(data == null)
{
    data_stream = getData(); // get memorystream
    cache.Add(key, data_stream.ToArray(), new CacheItemPolicy());
    data = (byte[])cache.Get(key);
}

using(Stream outputStream = new MemoryStream(decktemplate)) {
    Open file and do manupulation then save the file in cloud.
}

仍然收到以下错误:“算术运算导致溢出。”

以下是堆栈树:

   at MS.Internal.IO.Zip.ZipIOExtraField.ParseRecord(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage, UInt16 expectedExtraFieldSize)
   at MS.Internal.IO.Zip.ZipIOCentralDirectoryFileHeader.ParseRecord(BinaryReader reader, Encoding encoding)
   at MS.Internal.IO.Zip.ZipIOCentralDirectoryBlock.ParseRecord(BinaryReader reader, Int64 centralDirectoryOffset, Int32 centralDirectoryCount, Int64 expectedCentralDirectorySize)
   at MS.Internal.IO.Zip.ZipIOCentralDirectoryBlock.SeekableLoad(ZipIOBlockManager blockManager)
   at MS.Internal.IO.Zip.ZipIOBlockManager.get_CentralDirectoryBlock()
   at MS.Internal.IO.Zip.ZipArchive.GetFiles()
   at System.IO.Packaging.ZipPackage.ContentTypeHelper..ctor(ZipArchive zipArchive, IgnoredItemHelper ignoredItemHelper)
   at System.IO.Packaging.ZipPackage..ctor(Stream s, FileMode mode, FileAccess access, Boolean streaming)
   at System.IO.Packaging.Package.Open(Stream stream, FileMode packageMode, FileAccess packageAccess, Boolean streaming)
   at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.OpenCore(Stream stream, Boolean readWriteMode)
   at DocumentFormat.OpenXml.Packaging.PresentationDocument.Open(Stream stream, Boolean isEditable, OpenSettings openSettings)
   at DocumentFormat.OpenXml.Packaging.PresentationDocument.Open(Stream stream, Boolean isEditable)

标签: c#.netcachingmemorycache

解决方案


Storing a MemoryStream as an object in cache is a very bad idea, because multiple threads could be accessing it concurrently. It is a much better idea to store the payload, as perhaps a byte[] or ArraySegment<byte>, and use that to create a different MemoryStream for each caller. Otherwise, you are going to be tripping over yourself constantly:

byte[] payload = (byte[])cache.Get(key);
if (payload is null)
{
    payload = GetFilePayload();
    cache.Add(key, payload);
}
using(var memoryStream = new MemoryStream(payload, writable: false))
{
    // ...
}

推荐阅读