【发布时间】:2020-09-24 04:07:50
【问题描述】:
我有以下代码,用于使用 POST 将文件上传到 REST 服务。
它适用于较小的文件,但它会为较大的文件抛出异常,我的意思是大约 800 KB。
public async Task<bool> UploadInputFileAsync(FileDTO file)
{
using (HttpClientHandler httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
httpClientHandler.ClientCertificates.Add(clientCertificate);
string url = $"{Configuration.FileService.Url}";
using (HttpClient httpClient = new HttpClient(httpClientHandler))
{
httpClient.DefaultRequestHeaders.TransferEncodingChunked = true;
MultipartFormDataContent multiForm = new MultipartFormDataContent();
using (FileStream fs = System.IO.File.OpenRead(Path.Combine(Configuration.FileService.InputFilesPath, file.FileName)))
{
multiForm.Add(new StreamContent(fs), "file", file.FileName);
using (HttpResponseMessage response = await httpClient.PostAsync(url, multiForm))
{
response.EnsureSuccessStatusCode();
return true;
}
}
}
}
}
抛出的异常如下
System.Net.Http.HttpRequestException: Error while copying content to a stream.
---> System.IO.IOException: Unable to read data from the transport connection: 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.
--- End of inner exception stack trace ---
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Security.SslStream.<WriteSingleChunk>g__CompleteAsync|210_1[TWriteAdapter](ValueTask writeTask, Byte[] bufferToReturn)
at System.Net.Security.SslStream.WriteAsyncChunked[TWriteAdapter](TWriteAdapter writeAdapter, ReadOnlyMemory`1 buffer)
at System.Net.Security.SslStream.WriteAsyncInternal[TWriteAdapter](TWriteAdapter writeAdapter, ReadOnlyMemory`1 buffer)
at System.Net.Http.HttpConnection.WriteAsync(ReadOnlyMemory`1 source)
at System.Net.Http.HttpConnection.ChunkedEncodingWriteStream.<WriteAsync>g__WriteChunkAsync|2_0(HttpConnection connection, ReadOnlyMemory`1 buffer)
at System.IO.Stream.CopyToAsyncInternal(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
at System.Net.Http.HttpContent.CopyToAsyncCore(ValueTask copyTask)
--- End of inner exception stack trace ---
at System.Net.Http.HttpContent.CopyToAsyncCore(ValueTask copyTask)
at System.Net.Http.MultipartContent.SerializeToStreamAsyncCore(Stream stream, TransportContext context, CancellationToken cancellationToken)
at System.Net.Http.HttpContent.CopyToAsyncCore(ValueTask copyTask)
at System.Net.Http.HttpConnection.SendRequestContentAsync(HttpRequestMessage request, HttpContentWriteStream stream, CancellationToken cancellationToken)
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
使用 Wireshark 我得到以下流量,并且似乎在 FIN,ACK 之后连接没有正常关闭
任何帮助将不胜感激。
稍后编辑
感谢您的所有帮助。
看来我的问题是由 .NET Core 3.1 中仍然存在的 SocketsHttpHandler 实现中的错误产生的(尽管他们建议它已在 3.1 中修复),我发现这里描述了 https://github.com/dotnet/runtime/issues/27415
解决方案是添加
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
在方法的开头。
【问题讨论】:
-
在异常本身
An existing connection was forcibly closed by the remote host.. -
尝试增加连接超时,所以如果它需要更多时间来解析,那么连接将不会关闭,但在我看来,这里的问题可能是解析文件时出现的异常,您需要验证,强制关闭 HttpClient
标签: c# httpclient