My team recently refactored a Web API service to move some of the repetitive code into static methods. One method is related to extracting an uploaded file from the request. The method works in unit testing, but under load, is throwing exceptions. Part of the code was found in an SO post, but I'm concerned that, overall, we're not using it correctly. Here's the code:
internal static string ExtractFile(HttpRequestMessage request)
{
if (request.Content.IsMimeMultipartContent())
{
string uploadRoot = ServiceHelper.GetUploadDirectoryPath();
var provider = new MultipartFormDataStreamProvider(uploadRoot);
try
{
Task.Factory
.StartNew(() => provider = request.Content.ReadAsMultipartAsync(provider).Result,
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait();
}
catch(System.AggregateException ae)
{
if(log.IsErrorEnabled)
{
foreach(var ex in ae.InnerExceptions)
{
log.Error("ReadAsMultipartAsync task error.", ex);
}
}
var errorResponse = request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An error occurred while extracting the uploaded file from the request.");
throw new HttpResponseException(errorResponse);
}
var fileData = provider.FileData.First();
var localName = fileData.LocalFileName;
var content = File.ReadAllText(localName);
if (log.IsDebugEnabled)
{
var embeddedName = fileData.Headers.ContentDisposition.FileName;
log.DebugFormat("File {0} was successfully uploaded as '{1}'.", embeddedName, localName);
}
return content;
}
else
{
log.Error("Invalid request received. Request must be in a multipart/form-data request.");
var errorResponse = request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Request must be a multipart/form-data request and contain one file.");
throw new HttpResponseException(errorResponse);
}
}
Walking thru the logs, I see errors like these:
System.IO.IOException: Error reading MIME multipart body part. ---> System.IO.IOException ---> System.Net.HttpListenerException: The I/O operation has been aborted because of either a thread exit or an application request
HttpListenerRequest disposed
System.IO.IOException: Error reading MIME multipart body part. ---> System.IO.IOException ---> System.Net.HttpListenerException: An operation was attempted on a nonexistent network connection
This web service is running as a self-hosted OWIN Windows service. The file uploads are small (3k to 4k).
I can't recreate the issue with a single upload. The client that is talking to the service uses tasks to post files, but it doesn't usually run more than 4 or 5 tasks concurrently. My team and I are relatively new to .NET tasks. One of the developers is wondering if the TaskCreationOptions.LongRunning parameter is actually hurting more than it helps. Any suggestions?
Update:
I tried switching out the Task.Factory code with this:
var task = Task.Run(async () => await request.Content.ReadAsMultipartAsync(provider));
task.Wait();
provider = task.Result;
I'm still having some issues, but this seems to work better. Not sure why, though.
I had the same issue, it was resolved by adding following code in web.config
<system.web>
<httpRuntime maxRequestLength="30000000" />
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="30000000" />
</requestFiltering>
</security>
</system.webServer>
Source: http://stackoverflow.com/questions/20942636/webapi-cannot-parse-multipart-form-data-post
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With