【发布时间】:2016-12-24 13:04:00
【问题描述】:
我的团队最近重构了一个 Web API 服务,将一些重复的代码移动到静态方法中。一种方法与从请求中提取上传的文件有关。该方法在单元测试中有效,但在负载下会引发异常。部分代码是在 SO 帖子中找到的,但我担心总的来说,我们没有正确使用它。代码如下:
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);
}
}
浏览日志,我看到如下错误:
System.IO.IOException:读取 MIME 多部分正文部分时出错。 ---> System.IO.IOException ---> System.Net.HttpListenerException: I/O 操作由于线程退出或应用程序请求而中止
HttpListenerRequest 已处理
System.IO.IOException:读取 MIME 多部分正文部分时出错。 ---> System.IO.IOException ---> System.Net.HttpListenerException: 在不存在的网络连接上尝试了操作
此 Web 服务作为自托管的 OWIN Windows 服务运行。文件上传很小(3k 到 4k)。
我无法通过一次上传重新创建问题。与服务对话的客户端使用任务来发布文件,但它通常不会同时运行超过 4 或 5 个任务。我和我的团队对 .NET 任务还比较陌生。一位开发人员想知道 TaskCreationOptions.LongRunning 参数是否真的比它的帮助更大。有什么建议吗?
更新:
我尝试使用以下代码切换 Task.Factory 代码:
var task = Task.Run(async () => await request.Content.ReadAsMultipartAsync(provider));
task.Wait();
provider = task.Result;
我仍然遇到一些问题,但这似乎效果更好。不过不知道为什么。
【问题讨论】:
-
也许检查您的 Owin 配置的超时/保持活动设置?这可能是由于连接缓慢/不稳定造成的?
标签: c# asp.net-web-api