坦率地说,我很难过。这超出了我的经验。
我有一个C#MVC程序,它在MemoryStream中生成一个zip文件供下载。通过单击按钮来调用操作方法。
唯一的问题是,在某些情况下,潜在的文件大小很容易超过一个千兆,从我的阅读,这是一个常见的问题。我已尝试在IIS(IIS8)上的请求筛选中将最大允许内容长度提高到3000000000。我已经尝试将requestLimits maxAllowedContentLength添加到我的web.config中。 我甚至尝试通过多次调用action方法来破解zip(但没有成功),尽管我还没有得到任何确认/否认这甚至是可能的。
我可以忽略IIS或web.config中的任何设置吗?这可能是公司网络问题,在应用程序开发人员级别无法解决吗?
答案 0 :(得分:0)
好的,所以很难用400个字符或更少的字符来解释大概念,所以我想我只是在评论部分引起更多的混淆。此外,我认为我们已经足够接近一个"答案"因为你很可能会得到。
MemoryStream
的默认构造函数实际上将初始大小设置为0.实际上,初始大小设置为大约256,但由于初始大小主要是指导,并且它没有实际上声称空间直到它需要,它从0开始。
每次写入流时,它会检查写入的数量与缓冲区数组的剩余大小。如果它不适合写入,它会创建一个新的更大的缓冲区数组,并将旧的缓冲区数组复制到其中。通过这种方式,设置初始大小可以有所帮助,因为您从较大的初始缓冲区数组开始,您可能不需要增长该缓冲区。你可能有更好的机会获得一个连续的内存块,我稍后会解释它的重要性,但这实际上对你不利。如果您只需要1MB的文件,但是您要使用100MB 和进行初始化,那么不会有100MB的连续内存,那么您将获得OutOfMemoryException
,即使可能有1MB的连续内存。
无论您是否初始化,仍然存在某些不可变的事实。首先,MemoryStream
需要连续的内存。即使您在系统上技术上有可用内存,也可能没有大块可用内存。换句话说,如果你有4GB可用,但它全部碎片化,即使尝试在内存中创建1GB流也可能会失败,原因很简单,因为它无法保留1GB的连续内存。显然,您在内存中创建的文件越大,您遇到此问题的可能性就越大。 仅仅因为这个原因,我会说你没有提高系统内存量就会失去运气。有8GB,可能只有4-6GB实际可供IIS使用,然后在工作进程和线程之间进行拆分,您可以将可用RAM的25%左右作为连续空间占用的几率非常高不可能的。
下一个不可变的事实可能相关或不相关,但既然你没有指明,我会提到它。如果您的Web应用程序部署为32位,则任何对象的硬限制为2GB,这意味着MemoryStream
永远不会超过2GB(实际上大约为1.3) -1.6GB作为.NET代码消耗一些地址空间),任何尝试这样做的尝试都会导致OutOfMemoryException
,即使你在系统上有一些可笑的RAM,如1TB +。如果您的应用程序是64位,那么这不太可能是一个问题,因为您可以解决更多的内存,假设它已正确编译。但是,你不得不试图搞砸了,所以你应该没事。
最后,多次写入也会导致问题。正如我之前所说,缓冲区阵列响应写入而调整大小(如果需要)。每次调整大小时,新的缓冲区数组必须也能够适应连续的地址空间。因此,如果您从头开始编写了所有数据,则多次调整大小可能会导致您遇到OutOfMemoryException
您不会被击中的情况。这是初始化MemoryStream
可能有帮助的地方,但正如我之前所说,它也是一把双刃剑,因为你的初始缓冲区大小可能太大而不能开始,你最终会得到一个例外情况,你可能没有让它有机地成长。无论多长时间,都要尝试将所有内容一次性写入流中,而不是零敲碎打。