我有一个C# WebAPI,可以让用户上传文件。这个应用程序在http上运行得很好。但是当我为我的API添加https时,我发现它在小文件上运行得很好,但是对于大文件(〉60MB),请求只会等待2分钟,然后就失败了。在查看服务器日志后,我发现了这个异常:
Microsoft.AspNetCore.Connections.ConnectionResetException: An existing connection was forcibly closed by the remote host.
---> System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketAwaitableEventArgs.<GetResult>g__ThrowSocketException|5_0(SocketError e)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketAwaitableEventArgs.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal.SocketConnection.DoReceive()
--- End of inner exception stack trace ---
at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
at System.IO.Pipelines.Pipe.GetReadAsyncResult()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.IO.Pipelines.PipeReader.CopyToAsyncCore[TStream](TStream destination, Func`4 writeAsync, CancellationToken cancellationToken)
at Infrastructure.LocalStorage.Domain.UploadFile.UploadChunkFileStreamService.SaveFileChunkAsync(UploadFileCommand command, String fileChunkPath)
更疯狂的是,它在一个服务器上运行良好(我们在开发环境中设置了https),但在另一个服务器上就不行了。在这两种情况下,我们都使用了IIS。有什么办法可以解决这个问题吗?我是否遗漏了HTTPS的IIS配置?
注意事项:
- 我们已经使uploadReadAheadSize更大以避免413错误。
- 我添加了以下代码到我的服务器上的建议这个post(然而,这是一个
SocketException
而不是ConnectionResetException
,虽然消息是相同的)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
- 文件正由React应用程序从前端上传。
注意2:当我减少上传到服务器的数据块数量时,它工作正常,没有任何错误。现在我一次上传2个数据块。
4条答案
按热度按时间pkwftd7m1#
如果你要发布大量的数据,你需要在
Web.config
中指定请求限制、长度和最大执行时间,答案来自this thread。此外,this详细说明了该设置。
txu3uszq2#
对于IIS托管的应用程序,重要的是在web.config上设置requestLimits标记以获取更多信息:https://learn.microsoft.com/en-us/iis/configuration/system.webserver/security/requestfiltering/requestlimits/和堆栈中溢出(已应答)maxRequestLength for .Net 4.5.1 framework
同时增加web.config文件上requesttimeout:
xfb7svmp3#
这有两个部分:
1.配置.net WebAPI后端应用程序。上面的答案涵盖了app.config设置以及所需的C#调用。
1.将Web服务器配置为接受大于X MB的文件
有时也会出现第3、4、5或6部分,但这不太可能
1.如果你使用的是基于云的Azure Web应用,则需要高级Web应用服务计划。基本Web应用服务计划将文件限制为60 MB。
1.在前端调用者代码和后端服务器之间的任何防火墙、代理等都可能由于大小或超时而丢弃请求
1.如果您同时上传多个文件块,Web服务器可能会耗尽资源并发生阻塞。
1.由于数据量的原因,C#后端服务器上出现了某种死锁、文件写入阻塞或内存不足。我会显式清除任何C#字节数组、关闭任何文件、关闭并处理任何流等,并将变量设置为null。C#垃圾收集器最终会这样做,但最好强制将它们清理干净。
m1m5dgzv4#
“通信端例外状况(10054):远程主机强制关闭了现有的连接”意味着客户端异常断开连接。例如,如果客户端进程在连接过程中退出,则可能发生这种情况。
如果客户端在上载请求主体的过程中断开连接,则可能导致HttpContext.Request.Body.ReadAsync()抛出导致更高严重性的日志,这是非常罕见的。
如果你只是想修复这个问题,你可以尝试启用缓冲并在try/catch中清空整个请求主体。在catch中,你可以记录你想要的任何严重性的问题。如果你成功读取了整个主体,你可以将request.Body.Position设置回零,然后从你的主应用再次读取,而不用担心会看到IOException。
为请求主体启用多个读取的建议方法。下面是一个在自定义ASP.NET中间件的InvokeAsync()方法中使用的示例:
后备FileBufferingReadStream首先使用特定大小的内存流,然后福尔斯临时文件流。默认情况下,内存流的大小为30 KB。还有其他EnableBuffering()重载,它们允许指定不同的阈值和/或总大小限制:
我希望这对解决问题有帮助。