2016-08-16 1 views
1

간단히 말해서, 내 문제는 내가 컨트롤러를 통해 파일을 반환하려고하지만 때로는 파일이 다른 프로세스에 의해 잠겨서 컨트롤러가 null을 반환하게됩니다.예외가 왜 여기까지 튀어 나오고 있습니까?

내 컨트롤러 (이 정확한 것은 아니지만 상당의) 같았다

[HttpGet] 
public IHttpActionResult GetFile(int fileid) 
{ 
    string filepath = GetFilePathFromId(fileid); 
    return new FileDownload(filepath); 
} 

public class FileDownload : IHttpActionResult 
{ 
    private string FilePath { get; set; } 
    public FileDownload(string filePath) 
    { 
     FilePath = filepath; 
    } 
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
    { 
     HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new StreamContent(new FileStream(FilePath, FileMode.Open)) 
     }; 

     response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") 
     { 
      FileName = Path.GetFileName(FilePath) 
     }; 

     return Task.FromResult(response); 
    } 
} 

내가 이벤트 뷰어에서 보았을 때 이것은 때때로 일반적인 XML을 오류

<Error><Message>An error has occurred.</Message></Error> 

를 반환했다 , 예외가 발생했습니다.

프로세스가 '...'파일에 액세스 할 수 없습니다. b 그것은 다른 프로세스에 의해 에 의해 사용되고있다.

나는이 이유를 알고, 빠른 솔루션으로 나는 그러나, 이상하게도,이 여전히 XML 오류를 일으키는

 IHttpActionResult file = null; 
     var fiveSecondsLater = DateTime.Now.AddSeconds(5); 
     while(DateTime.Now < fiveSecondsLater) 
     { 
      try 
      { 
       file = new FileDownload(filepath); 
       break; 
      } 
      catch 
      { 
       Thread.Sleep(500); 
      } 
     } 
     return file ?? Content(HttpStatusCode.InternalServerError, "Could not access file."); 

했다! 예외를 잡아서 다시 던지지 않기 때문에 매우 이상합니다. 어떤 결함이 여기에 있으며 어떻게 해결할 수 있습니까?

편집 :

스택 추적 점은 문제 하나

HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK) 

을 줄 수 있습니다. 스택 추적 대신 때때로 나중에 제가 파일이 프로세스에 의해 잠겨 왜 근본 원인을 검색하는 것이 좋습니다 열린 파일 작업을 다시 시도 할 수있는 빠른 수정의

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) 
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) 
    at System.IO.FileStream..ctor(String path, FileMode mode) 
    at ....FileDownload.ExecuteAsync(CancellationToken cancellationToken) in ...:line 81 
    at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext() 
+2

XML 응답이 매우 일반적인 것처럼 보입니다. 아마 다른 예외가 그것을 일으키는 것입니까? 이번에는 정확한 예외가 무엇이고 어떤 행이 그것을 던집니까? – David

+0

@David 동일합니다. 위의 스택 추적을 게시 할 예정입니다. –

+0

GetFile을 호출하는 동안 발신자가 시간 초과되지 않도록하고 다운로드가 시작될 때까지 파일이 다시 잠기지 않도록 할 수 있습니까? – ostati

답변

0

같다.

FileStream 생성 논리를 변경하여 스트림을 독점적으로 열어 볼 필요가 있습니다. 다음과 같이 약간 확장 된 생성 논리는 파일 잠금 위험을 줄입니다.

Content = new StreamContent(
      new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
관련 문제