Reputation: 73
I am trying to POST a specific file using HttpClient (.NET 6.0) and MultipartFormDataContent
, but I keep getting the following error: Error while copying content to a stream
However, when uploading the file through Postman or through the server's own web portal, it was successful. Unfortunately I don't have access to the remote server to know why it is failing.
Below is the sample code with some information removed.
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());
}
}
Here is the following stacktrace of the error:
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.
I've seen a similar post, but did not see any solution that would help with my situation:
I am not sure if the problem is in my code, but any thoughts or ideas would be appreciated.
Upvotes: 2
Views: 3698
Reputation: 73
I've identified the issue, and it turns out MultipartFormDataContent
is adding double quotes around the boundary value by default, while both the server web portal and Postman did not.
This is an example of what the Content-Type for MultipartFormDataContent
would look like if inspected:
multipart/form-data; boundary="85707dac-07d6-4978-8a35-32c09f6c5b7c"
However, the remote server was expecting no quotes in the boundary value, like the following:
multipart/form-data; boundary=85707dac-07d6-4978-8a35-32c09f6c5b7c
To get around this problem, I've removed the double quotes around the boundary field with the following:
var contentType = multipartFormContent.Headers.ContentType.Parameters.First();
contentType.Value = contentType.Value.Replace("\"", String.Empty);
This Github issue is what got my attention into looking at the boundary value: https://github.com/dotnet/aspnetcore/issues/41237
This post is where I got the solution to remove the double quotes from the boundary: https://stackoverflow.com/a/48371123
Upvotes: 4
Reputation: 199
We had this issue in a previous project. What worked for us was to use one of the overloads of the add method that required the name
and fileName
parameters.
multipartFormContent.Add(new ByteArrayContent(fileBytesArray), "name", "fileName")
Upvotes: 0