如何将大 (> 25MB) 文件上传到 Web 服务?

Posted

技术标签:

【中文标题】如何将大 (> 25MB) 文件上传到 Web 服务?【英文标题】:How do I upload large (> 25MB) files to a web service? 【发布时间】:2010-11-03 04:35:36 【问题描述】:

我有一个网络服务,它接受一个字节[]并保存它。

这适用于“小”文件,但一旦达到一定大小,Web 服务就会失败并返回“请求失败,HTTP 状态 404:未找到。”

据我所知,这似乎是一个 IIS 设置,它限制了可以发布的文件的大小(以防止拒绝服务攻击)。我试图增加该设置,但我无法确定设置什么以及在哪里/如何设置它。我正在使用 IIS7,并且 web 服务是在 .net (asmx) 中完成的。

在 web 服务的 web.config 中,我添加了以下内容(这似乎增加了可以接受的文件大小,但不是一直到这个设置大小)

  <system.web>
     <httpRuntime executionTimeout="999999" maxRequestLength="2097151" />
     ...
  </system.web>

任何关于在何处(以及如何)增加 Web 服务文件大小的建议将不胜感激。

【问题讨论】:

关于 WCF/FTP/WS-Attachment/DIME:很好的建议和一些有趣的阅读。这些可能是我最终将使用的长期解决方案类型。但是,如果有一些短期解决方案可以更改 IIS7 中的上传大小,那就太好了。谢谢。 【参考方案1】:

除了问题中提到的 httpRuntime/maxRequestLength 之外,似乎还有一个附加项可以添加到 Web 服务的 web.config 文件中以允许大文件传输。

  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="2000000000" />
      </requestFiltering>
    </security>
  </system.webServer>

这似乎可以通过网络服务上传更大的文件。

【讨论】:

请注意:当您从 WCF 服务获得 404 但在 WCF 跟踪中没有错误消息时,表明您缺少此设置(是的,我知道非常有帮助 - 谢谢WCF)。很高兴你找到了这个 Chris,你让我在这上面浪费了更多的时间。 是的,今天这个“额外”设置浪费了我一天中的许多小时。我没有意识到,使用 IIS7,您需要在 web.config 的两个位置引用最大的文件大小。但是,是的,有了这个 maxAllowedContentLength 设置,我终于可以上传 31Mb 的文件了。 @AndyBritcliffe “感谢 WCF”。在我看来,在这种情况下 404 源自 IIS 本身,因此 WCF 可能甚至没有听说过该事件,因此几乎没有机会记录任何有关它的内容。改写为“感谢微软”,批评仍然存在。 :) 又一票感谢,这已经让我头疼了 小时【参考方案2】:

您应该记住,Web 服务主要不是作为文件传输机制设计的。任何专门设计的文件传输协议都可能比 Web 服务做得更好。例如,此类协议更有可能处理错误恢复、部分上传等问题。

但是,如果您打算在 .NET 中为此目的使用 Web 服务,则应尽可能使用 WCF。除了其他好处之外,WCF 处理流式传输,因此在内存使用方面效率更高。我担心如果您遵循上面的两个(准确)建议,您的下一个结果将是“内存或资源不足”异常,因为旧的 ASMX 技术试图一次将整个 25MB 文件加载到内存中。事实上,它可能同时在内存中有多个副本!

【讨论】:

【参考方案3】:

如果我不得不使用 Web 服务并且需要支持非常大的文件,我会考虑实施一个允许您分段上传文件的系统。

例如。

ticketId GetTicket(大小) UploadData(ticketId, byte[] payload)(这个可以调用多次) FinalizeUpload(ticketId)

这将允许您将大量上传内容分块,而不会在内存中保存太多数据。缺点是您仍在使用效率相当低的传输机制。

【讨论】:

这应该是公认的解决方案,因为它占用的内存更少,甚至可以支持并行性。【参考方案4】:

只是向搜索此 web.config 的人添加信息:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI

<location path="Copy.asmx"> <!-- Name of you asmx -->
    <system.webServer>
      <security>
        <requestFiltering>
          <requestLimits maxAllowedContentLength="104857600"/> <!-- 100 megs -->
        </requestFiltering>
      </security>
    </system.webServer>
  </location>

在解决此问题相当长的一段时间后,这解决了我们的问题。

【讨论】:

【参考方案5】:

如果您打算使用 Web 服务来移动文件,我至少会考虑使用 WS-Attachment / DIME 附件。通过 Web 服务发送 byte[] 的主要问题是它们被放入 SOAP 主体中,该主体被编码为 base 64 字符串。像这样对文件进行编码文件大小在soap主体中增加了三分之二(即,6 MB 的文件通过网络变成了 9 MB 的文件)。

您上传的 25 MB 文件可能会变成巨大的肥皂信封。

我强烈建议 reading this. 这可能会让你进入 DIME。

这是一段摘录。

Microsoft 的 WSE 工具包允许大型 附件一起发送 使用 DIME 的 Web 服务方法和 WS-附件标准。好吧 检查这些标准及其原因 比发送大数据更有效率 Web 中的二进制数据量 通过其他常见的服务调用 意思。

希望有帮助!

【讨论】:

正是我要建议的。 XML 拒绝服务过滤器将缓冲整个 SOAP 消息,并且缓冲区大小是有限的。将 base-64 编码的二进制文件作为附件发送可以避免这种情况。 DIME 将使 Java、php 和其他客户端也更容易使用该服务。 抱歉,WSE 已过时。除非您没有其他选择,否则不要使用它。很抱歉,但似乎不是每个人都听说过这一点,或者不是所有人都知道 Visual Studio 2008 或更高版本不支持 WSE。 John 提出了一个很好的观点,WSE 已被弃用,与 WCF 相比,它的路线图相当黯淡。话虽这么说,如果我们谈论的是对现有 Web 服务的更新,而该服务不会大修到 WCF(或 .NET v3.0+ 框架不可行),我会坚持我的观点并推荐 DIME /WS-附件。 @Tyler:你可能想在这里查看我的个人资料,看看这是否能让事情更清楚。 WSE 的正确用词不是“已弃用”,而是“已过时”。与“已弃用”可能暗示的相比,它更接近于实际上不受支持。确实,WSE 的正确答案是“不要去那里”。见social.msdn.microsoft.com/Forums/en-US/asmxandxml/thread/…。 这在搜索了 2 小时后救了我,如果您的文件限制为 10 mgb,您需要对网络服务设置更大的限制。谢谢【参考方案6】:

maxRequestLength 以 KB 为单位,而不是字节。这应该会在 4 分钟的超时窗口内为您提供 30 MB 的限制。

<httpRuntime executionTimeout="240" maxRequestLength="30000" />

数字过高实际上可能会阻止您的值被应用。我认为几年前我遇到了这个问题,当时我认为这是一个字节限制(模糊的内存)。

【讨论】:

我更改为这些值,结果相同。我从这篇(有些相关/有些不相关)文章中获取的值:support.microsoft.com/kb/925083 - 两个值集似乎都有相同的问题。 接收页面上的 ScriptTimeout 设置为多少?【参考方案7】:

这并没有具体回答您的问题,但我过去所做的是使用 WCF 传输文件名/路径/列表,然后使用 FTP 库通过 FTP 传输文件。

【讨论】:

【参考方案8】:

这对我有用:

            <binding name="uploadFilesBasicHttpBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:10:10" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00">
                <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
                <security mode="TransportWithMessageCredential">
                    <message clientCredentialType="UserName"/>
                </security>
            </binding>

【讨论】:

宾果游戏! docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/…

以上是关于如何将大 (> 25MB) 文件上传到 Web 服务?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 AppendBlob/大于 4mb 限制的文件上传到 Java 中的 Azure 存储/Blob?

将大文件上传到 sitecore 媒体库

如何有效地将大文件加载到 IndexedDB 存储中?我的应用程序在超过 100,000 行时崩溃

C#如何将大文件上传到ftp站点

文件上传到 azure 文件共享不适用于更大的文件

如何使用 GoogleDrive REST API 将大文件 (1 GB +) 上传到 Google Drive