我试图搜索互联网/堆栈溢出,但找不到任何对我有用的相关答案。
我有一个 asp.net web api2 应用程序(仅使用 ssl)。我正在尝试允许大文件上传(最多 ~36mb),但除非我将 uploadReadAheadSize 更改为预读这个大小,否则我会从 IIS 收到一个错误,即请求太长。
我不想设置该属性,因为这样我的数据流只有在 IIS 已经全部读取后才到达。
我的问题是:如何在没有配置大的 uploadreadaheadsize 的情况下使用托管的 asp.net 并使用 ssl(!)和 web api 2 进行大文件上传?因为我采取的所有步骤似乎都不够。
上传预读大小:
指定 Web 服务器将读入缓冲区并传递给 ISAPI 扩展或模块的字节数。每个客户端请求都会发生一次。ISAPI 扩展或模块直接从客户端接收任何附加数据。该值必须介于 0 和 2147483647 之间。默认值为 49152。
如果我没有设置 uploadReadAheadSize 并尝试通过 ssl 上传大文件,这是我得到的错误:
HTTP 错误 413.0 - 请求实体太大
您可以尝试的事情:页面未显示,因为请求实体太大。
最可能的原因:
Web 服务器拒绝为请求提供服务,因为请求实体太大。Web 服务器无法为请求提供服务,因为它正在尝试协商客户端证书,但请求实体太大。请求 URL 或 URL 的物理映射(即 URL 内容的物理文件系统路径)太长。您可以尝试的事情:验证请求是否有效。如果使用客户端证书,请尝试:
增加 system.webServer/serverRuntime@uploadReadAheadSize
配置您的 SSL 端点以协商客户端证书作为初始 SSL 握手的一部分。(netsh http 添加 sslcert ... clientcertnegotiation=enable)
Verify that the request is valid.
If using client certificates, try:
Increasing system.webServer/serverRuntime@uploadReadAheadSize
Configure your SSL endpoint to negotiate client certificates as part of the initial SSL handshake. (netsh http add sslcert ... clientcertnegotiation=enable)
如果我将预读配置为我想要允许的大小,iis 允许我的请求:
C:\Windows\SysWOW64>C:\Windows\System32\inetsrv\appcmd set config ... -section:system.webServer/serverRuntime /uploadReadAheadSize:n /commit:apphost
Applied configuration changes to section "system.webServer/serverRuntime" for "MACHINE/WEBROOT/APPHOST/..." at configuration commit path "MACHINE/WEBROOT/APPHOST"
我在 web.config 中配置了这个:
...
<httpRuntime targetFramework="4.5.1" maxRequestLength="36864" />
...
和
...
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="37748736">
...
我有一个接收文件的虚拟控制器
[ControllerBufferlessAttribute()]
public class UploadController : ApiController
{
public HttpResponseMessage Post([FromUri]string filename)
{
var selector = RequestContext.Configuration.Services.GetHostBufferPolicySelector();
var isbufferless = string.Format("It is {0} that i'm bufferless but still IIS already read all the data before this context because of the readahead", selector is PolicySelectorBufferless);
return new HttpResponseMessage(HttpStatusCode.InternalServerError) { ReasonPhrase = isbufferless };
}
}
属性和策略:
public class ControllerBufferlessAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings settings,
HttpControllerDescriptor descriptor)
{
settings.Services.Replace(typeof(IHostBufferPolicySelector), new PolicySelectorBufferless());
}
}
public class PolicySelectorBufferless : WebHostBufferPolicySelector
{
public override bool UseBufferedInputStream(object hostContext)
{
return false;
}
public override bool UseBufferedOutputStream(HttpResponseMessage response)
{
return base.UseBufferedOutputStream(response);
}
}
我在请求中得到的内容
确实,我是无缓冲的,但由于预读,IIS 仍然已经读取了此上下文之前的所有数据