MultipartFormDataStreamProvider有时会在上传后立即读取文件

时间:2013-07-19 20:44:35

标签: c# asp.net-web-api

我有一些Web API代码,我是从SO帖子和其他网站组装的。然而,任务的东西对我来说仍然是新的。我正在尝试将上传的文件复制到新位置,但有时(并非所有时间)我在尝试复制文件时遇到异常。该异常表示该文件正由另一个进程使用。但是,每次都不会发生这种情况。我想我需要在其他地方移动复制操作。这是我的代码。有什么建议吗?

var provider = new MultipartFormDataStreamProvider(uploadroot);
                var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith<HttpResponseMessage>(t =>
                {
                    if (t.IsFaulted || t.IsCanceled)
                        throw new HttpResponseException(HttpStatusCode.InternalServerError);

                    var docConversionId = Guid.NewGuid().ToString("N");
                    var sourceFilePath = Path.Combine(uploadroot, provider.FileData.First().LocalFileName);
                    var destinationFilePath = Path.Combine(inboxroot, docConversionId);

                    File.Copy(sourceFilePath, destinationFilePath);

                    var response = new HttpResponseMessage(HttpStatusCode.OK);
                    response.Content = new StringContent(docConversionId);
                    //response.Content.Headers.Add("DocumentConversionId", docConversionId);
                    return response;
                });
                return task;

3 个答案:

答案 0 :(得分:7)

使用ReadAsMultipartAsync后,尝试读取/删除文件时可能会遇到已知问题。

以下是与之相关的错误(您可以查看解决方案信息,了解更多详情,了解其发生的原因以及解决方法):

https://aspnetwebstack.codeplex.com/workitem/176

答案 1 :(得分:1)

由于codeplex中的原始讨论已死,因此我将此处的原始解释和解决方法粘贴到了该问题于2013年最初关闭时:

  

我们正在解决此问题,因为找到了根本原因   框架代码。已针对外部设备打开了一个单独的错误   合作伙伴团队,并将在此处跟踪该问题。

     

变更集:   http://aspnetwebstack.codeplex.com/SourceControl/changeset/changes/452b8e1dfa40

     

还原尝试使用FileOptions.WriteThrough的尝试修复   确保它不是文件高速缓存和FileStream代码之间的竞争。   但是WriteThrough并未解决核心错误并导致性能下降   退化。

     

对用户代码的影响是这样的:如果您使用   MultipartFormDataContent并使用以下命令在服务器上读取   MultiPartDataStreamProvider,服务器上的基础文件可能不   ReadAsMultipartAsync完成后完全关闭。有一个   本地代码可能仍在释放文件资源的小窗口   在另一个线程上。

     

影响是对该文件执行了File.Delete或File.OpenRead   异步读取后可能立即失败,并出现IOException(“ file   正在被另一个过程使用”)。我们观察到大约0.3%的故障率   高负载情况。唯一已知的解决方法是尝试/捕获   围绕这些操作,如果发生IOException,请延迟一小段时间,   然后重试。通常50ms的延迟有效,但允许多个   建议重试。这允许本机线程完成   释放其资源。在我们的压力实验室中   catch-delay-and-try算法总是成功。

答案 2 :(得分:0)

我遇到了一个疯狂的问题,发现它可以与await关键字一起使用。

await Request.Content.ReadAsMultipartAsync(streamProvider);

不将任务保存在变量中。