.NET 6.0 使用 HttpClient 发布 MultipartFormDataContent 结果 'Error while copying content to a stream'

.NET 6.0 Posting MultipartFormDataContent with HttpClient result in 'Error while copying content to a stream'

我正在尝试 POST 使用 HttpClient (.NET 6.0) 和 MultipartFormDataContent 的特定文件,但我不断收到以下错误:Error while copying content to a stream

但是,当通过Postman或通过服务器自己的门户网站上传文件时,它是成功的。不幸的是,我无法访问远程服务器,无法知道它失败的原因。

下面是删除了一些信息的示例代码。

public static class Program {
    private static HttpClient client;
    private static HttpClientHandler httpClientHandler;

    private static async Task Main() {
        httpClientHandler = new HttpClientHandler() {
            ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
        };

        client = new HttpClient(httpClientHandler);
        client.BaseAddress = new Uri("https://remoteServerIpAddress/");

        var filePath = "absoluteFilePath";
        var fileBytesArray = File.ReadAllBytes(filePath);

        var multipartFormContent = new MultipartFormDataContent();
        multipartFormContent.Add(new ByteArrayContent(fileBytesArray));

        // Setup headers for authorization

        // Error occurs here
        var uploadResponse = await client.PostAsync("api/upload", multipartFormContent).ConfigureAwait(true);

        Console.WriteLine(await uploadResponse.Content.ReadAsStringAsync());
    }
}

下面是错误的堆栈跟踪:

System.Net.Http.HttpRequestException
  HResult=0x80131620
  Message=Error while copying content to a stream.
  Source=System.Net.Http
  StackTrace:
   at System.Net.Http.HttpContent.<<CopyToAsync>g__WaitAsync|56_0>d.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at System.Net.Http.MultipartContent.<SerializeToStreamAsyncCore>d__23.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.HttpContent.<<CopyToAsync>g__WaitAsync|56_0>d.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at System.Net.Http.HttpConnection.<SendRequestContentAsync>d__68.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.HttpConnection.<SendAsyncCore>d__62.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Net.Http.HttpConnection.<SendAsyncCore>d__62.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at System.Net.Http.HttpConnectionPool.<SendWithVersionDetectionAndRetryAsync>d__83.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.RedirectHandler.<SendAsync>d__4.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at System.Net.Http.HttpClient.<<SendAsync>g__Core|83_0>d.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Program.<Main>d__2.MoveNext() in C:\Projects\UploadApplication\Program.cs:line 59

Inner Exception 1:
IOException: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host..

Inner Exception 2:
SocketException: An existing connection was forcibly closed by the remote host.

我见过类似的 post,但没有看到任何对我的情况有帮助的解决方案:

我不确定问题是否出在我的代码中,但如果有任何想法或想法,我们将不胜感激。

我们在之前的项目中遇到过这个问题。对我们有用的是使用需要 namefileName 参数的 add 方法的重载之一。

multipartFormContent.Add(new ByteArrayContent(fileBytesArray), "name", "fileName")

我已经确定了问题,事实证明 MultipartFormDataContent 默认在边界值周围添加双引号,而服务器 Web 门户和 Postman 没有.

这是检查 MultipartFormDataContent 的 Content-Type 的示例:

multipart/form-data; boundary="85707dac-07d6-4978-8a35-32c09f6c5b7c"

但是,远程服务器期望边界值中没有引号,如下所示:

multipart/form-data; boundary=85707dac-07d6-4978-8a35-32c09f6c5b7c

为了解决这个问题,我删除了边界字段周围的双引号:

var contentType = multipartFormContent.Headers.ContentType.Parameters.First();
contentType.Value = contentType.Value.Replace("\"", String.Empty);

这个 Github 问题引起了我对边界值的关注: https://github.com/dotnet/aspnetcore/issues/41237

这个 post 是我从边界中删除双引号的解决方案: