如何在ASP.net MVC HttpPost中上传大文件

时间:2015-09-23 13:21:59

标签: c# asp.net asp.net-mvc file asp.net-mvc-4

我尝试在ASP.net MVC中上传大文件,然后保存在DB中。 但是,当我这样做时,我已经" outofmemoryexception"。 在这里,我发布我的文件:

[HttpPost]
        public void UploadAttachments(int docId, int folderId)
        {
            if (Request.Files.Count <= 0) return;  //throw exception?
            for (var i = 0; i < Request.Files.Count; i++)
            {
                try
                {
                    var file = Request.Files[i];

                    ProjectAttachmentInput attachment = new ProjectAttachmentInput();
                    attachment = SetAttachment(attachment, file, docId, folderId);
                    _documentationAppService.SaveUploadedFile(attachment);

                }
                catch { }
            }
        }

接下来在SetAttachment()中:

private ProjectAttachmentInput SetAttachment(ProjectAttachmentInput attachment, HttpPostedFileBase file, int docId, int folderId)
        {   
            attachment.FileName = file.FileName;
            attachment.FileContent = ReadFully(file.InputStream);
            attachment.ProjectAttachmentId = docId;
            attachment.ProjectAttachmentFolderId = folderId;
            return attachment;
        }

当我尝试使用ReadFully时,我得到了OutOfMemoryException ...

private static byte[] ReadFully(Stream input)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }

错误是我尝试输入时.CopyTo(ms) 我需要从文件中的byte []然后将其保存在DB中。 如果文件小于100MB,则此方法有效。 但是当我尝试200MB时,我有例外......

此代码应该更改什么?

我的web.config配置:

<system.webServer>
    <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="2147483648" />
    </requestFiltering>
  </security>
...
 <httpRuntime maxRequestLength="1073741824" targetFramework="4.5.1" />

2 个答案:

答案 0 :(得分:1)

首先,如果您希望将大型文件上传到您的网站,则应使用流式IO并且永远不要将整个文件加载到内存中。

其次,将文件存储在数据库中并不是一个好主意,IMO(即使使用this MSDN article - 再次,这是我自己的看法。)

有了这两点,我就是为您提供的:

  1. 将文件存储在FILESTREAM的文件系统中。您可以使用纯流式IO,文件大小不会成为问题(只要您的磁盘未满)
  2. 在您的数据库中,仅保留文件哈希值
  3. “内容可寻址”部分意味着,实际上,无论何时将文件保存到文件系统,首先要计算文件的哈希值,然后然后将此哈希值用作文件名。这将为您提供自动内容重复数据删除,您将不依赖于文件名。

答案 1 :(得分:1)

这是因为您尝试将整个文件加载到内存中的数组中。这里的好习惯是使用流而不是数组,并将数据块作为BLOB保存在数据库块中(如果您确实希望将文件存储在数据库中,这是一个值得商榷的选择)。

但是,为了将流保存为BLOBS,您必须执行额外的步骤。

也许这篇文章可以帮到你(我不知道你正在使用什么类型的数据库)

https://www.mssqltips.com/sqlservertip/1489/using-filestream-to-store-blobs-in-the-ntfs-file-system-in-sql-server-2008/