2016-08-16 4 views
1

Kurz gesagt, mein Problem ist, dass ich versuche, eine Datei über einen Controller zurückzugeben, aber manchmal wird die Datei von einem anderen Prozess gesperrt, so dass mein Controller null zurückgibt.Warum brodelt hier die Ausnahme?

Mein Controller war wie (Dies ist nicht die genaue ist, aber es ist äquivalent)

[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); 
    } 
} 

und dies wurde manchmal eine generische XML Fehler zurückgegeben

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

Als ich in der Ereignisanzeige sah Ich sah, dass eine Ausnahme ausgelöst wurde

Der Prozess kann nicht auf die Datei '...' zugreifen b Weil es von einem anderen Prozess verwendet wird.

Ich weiß, warum dies so ist, und als eine schnelle Lösung habe ich

 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."); 

jedoch seltsam genug, dies immer noch den XML-Fehler verursacht wurde! Sehr seltsam, da ich die Ausnahme abfange und sie nicht erneut werfe. Irgendeine Idee, was der Fehler hier ist und wie ich es beheben kann?

EDIT:

Punkte-Stack trace

HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK) 

als das Problem einer Linie. Stack-Trace ist wie

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

Diese XML-Antwort sieht ziemlich generisch. Vielleicht verursacht eine andere Ausnahme es? Was ist diesmal die genaue Ausnahme und welche Zeile wirft sie? – David

+0

@David Es ist das gleiche. Ich werde den Stack-Trace oben veröffentlichen. –

+0

Können Sie sicherstellen, dass der Aufrufer beim Aufruf von GetFile keine Zeitüberschreitung durchführt, und vielleicht auch sicherstellen, dass die Datei nicht bis zum Start des Downloads erneut gesperrt wird? – ostati

Antwort

0

Statt die schnelle Lösung der offenen Dateioperation erneut zu versuchen, manchmal später empfehle ich für die Ursache zu suchen, warum die Datei von einem Prozess gesperrt ist.

Es ist einen Versuch wert, die Erstellungslogik FileStream so zu ändern, dass der Stream nicht exklusiv geöffnet wird. Die folgende leicht erweiterte Erstellungslogik reduziert das Risiko von Dateisperren.

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