系统.OutOfMemoryException:上传文件时出现异常

3

上传一个84MB的文件时,出现了以下错误(请参见以下错误),但是当我上传一个约60MB的文件时,一切正常。这仅在我们的32位2008 VM w / 4GB内存上发生。在我的R2 64位VM w / 8GB内存上,即使130MB文件也可以正常工作。

System.OutOfMemoryException:引发类型为'System.OutOfMemoryException'的异常。于 System.IO.BinaryReader.ReadBytes(Int32 count)于 CustWeb.Controllers.DownloadsController.Create(Download dl, HttpPostedFileBase file) 在 c:\...\CustWeb\Controllers\DownloadsController.cs:line 72

我监视任务管理器中的内存,整个上传过程中它从未超过74%。

这是一个基于4.5 .NET框架的MVC 4应用程序。

我在我的web.config中设置了上传文件的最大设置。

<httpRuntime requestValidationMode="4.5" targetFramework="4.5" maxRequestLength="2147483647" executionTimeout="84000" />

...

<security>
     <requestFiltering>
         <requestLimits maxAllowedContentLength="2147482624" />
     </requestFiltering> 
</security>

更新 根据要求添加代码:

    public ActionResult Create(Download dl, HttpPostedFileBase file)
    {
        try
        {
            using (var binaryReader = new BinaryReader(file.InputStream))
            {
                dl.FileBytes = binaryReader.ReadBytes(file.ContentLength);
            }
            dl.FileContentType = file.ContentType;
            dl.FileName = file.FileName;
            dl.Insert();
            Success("<strong>" + dl.Label + "</strong> created and uploaded successfully.");
            return RedirectToAction("Index");
        }
        catch (Exception ex)
        {
            SelectList list = new SelectList(new DownloadType().GetDownloadTypes(), "ID", "Name");
            ViewBag.DownloadTypeList = list;
            Error(ex.ToString());
            return View(dl);
        }
    }

在这里使用BinaryReader是错误的。 - leppie
@SLaks - 按照您的要求,我已经添加了我的代码。 - RichC
@leppie 我添加了我的代码 - 除了使用BinaryReader,还有更好的方法来完成我正在做的事情吗? - RichC
@leppie - 我已经将它从BinaryReader更改为仅使用MemoryStream,但我仍然遇到相同的错误。 - RichC
2个回答

3

默认情况下,ASP.NET 允许使用可用内存的 60% - 请检查 machine.config 中的 processModel 的 memoryLimit。您可以将该值更改为,例如 80% ,以给 ASP.NET 更多的空间,但这并不推荐。考虑其他选项,例如分块上传文件。


哇 - 你是如何分块上传文件的? - RichC
有不同的方法可以使用HTTP模块,例如:http://dotnetslackers.com/Community/blogs/haissam/archive/2008/09/12/upload-large-files-in-asp-net-using-httpmodule.aspx,也可以使用第三方控件,例如:http://www.plupload.com/。但是,在尝试使用上面显示的web.config文件中的`httpRuntime`部分的`requestLengthDiskThreshold`属性之前,请尝试进行调整。它可以控制服务器在将上传的文件缓存到磁盘之前可以在内存中保存的大小。 - Yuriy Galanter
默认值似乎是256字节,以防止使用过多的内存。增加它似乎会使用更多的内存,并使问题变得更糟,不是吗? - RichC
1
对于.NET 4.5,默认值为80千字节,但你说得对,增加它会使情况变得更糟。那么就不要考虑这个属性了,不幸的是它对你没有帮助。我的想法是如果默认值太大-尝试减少它,但事实并非如此。 - Yuriy Galanter

0

我将它从流式转换为文件保存,这样就避免了内存错误。

    public ActionResult Create(Download dl, HttpPostedFileBase file)
    {
        try
        {
            string tempFile = Path.Combine(Server.MapPath("~/App_Data/"), string.Format("{0}_{1}",Guid.NewGuid().ToString(), Path.GetFileName(file.FileName)));
            file.SaveAs(tempFile);
            dl.FileBytes = System.IO.File.ReadAllBytes(tempFile);
            dl.FileContentType = file.ContentType;
            dl.FileName = file.FileName;
            dl.Insert();
            System.IO.File.Delete(tempFile);
            Success("<strong>" + dl.Label + "</strong> created and uploaded successfully.");
            return RedirectToAction("Index");
        }
        catch (Exception ex)
        {
            SelectList list = new SelectList(new DownloadType().GetDownloadTypes(), "ID", "Name");
            ViewBag.DownloadTypeList = list;
            Error(ex.ToString());
            return View(dl);
        }
    }

我仍然偶尔会遇到内存错误,但将其更改为这种方法确实提高了我能够上传的文件大小(增加了一倍)。我想我必须增加实际的RAM才能处理比160MB更大的文件。 - RichC
经过一些阅读后,我的问题不是上传文件,而是在将其保存到数据库之前的readAllBytes。而且如果我要可能保存200MB+的文件,我应该将它们存储在文件系统中,并保存对数据库的引用。 - RichC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接