2012-10-04 82 views
3

我正在使用Web Api創建一種通過Web API上傳文件的方式。我發現了幾篇關於如何完成這篇文章的博文,代碼與Request.Content.ReadAsMultipartAsync()調用的關鍵通用性非常相似。我遇到的問題是第一次上傳可以正常工作,但隨後IIS進入故障狀態,導致後續上傳失敗。第一個32Kb進來,但它然後退出。調試只顯示出現在ASP.NET框架某處的空引用異常。通過Web上傳文件Api第二次上傳失敗

這裏是ApiController定義我...

public class FileUploadController : ApiController 
{ 
    public void Post() 
    { 
     if (Request.Content.IsMimeMultipartContent()) 
     { 
      var path = HttpContext.Current.Server.MapPath("~/App_Data"); 
      var provider = new MultipartFormDataStreamProvider(path); 
      var task = Request.Content.ReadAsMultipartAsync(provider); 
      task.ContinueWith(t => 
      { 
       if (t.IsFaulted || t.IsCanceled) 
        throw new HttpResponseException(HttpStatusCode.InternalServerError); 
      }); 
     } 
     else 
     { 
      throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted")); 
     } 
    } 
} 

而且,這裏是我從張貼在網頁...

<!doctype html> 
<head> 
    <title>File Upload Progress Demo #3</title> 
</head> 
<body> 
    <h1>File Upload Progress Demo #3</h1> 
    <code>&lt;input type="file" name="myfile[]"></code><br> 
    <form action="/api/fileupload" method="post" enctype="multipart/form-data"> 
    <input type="file" name="myfile"><br> 
    <input type="submit" value="Upload File to Server"> 
    </form> 

    <div class="progress"> 
     <div class="bar"></div> 
     <div class="percent">0%</div> 
    </div> 

    <div id="status"></div> 
</body> 

上面的代碼可以在默認下載來自https://github.com/JohnLivermore/FileUploadTest的WebApi解決方案。運行並導航至http://localhost:{port}/FormPost.html。第一個上傳成功(上傳到App_Data),但後續上傳僅上載第一個32 Kb,然後失敗。

+0

此代碼是在.NET 4還是.NET 4.5上運行? – tugberk

回答

5

你不應該使用一個void方法。

由於多種原因,無效和異步不能很好地協同工作。

public Task<HttpResponseMessage> Post() 
    { 
     var rootUrl = "c:/uploads"; 

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

      //do stuff with files if you wish 

      return new HttpResponseMessage(HttpStatusCode.OK); 
     }); 
     return task; 
     } 

     throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted")); 
    } 
+1

兩個答案都是正確的,但是這個更適用於我的情況。 –

+0

同一個!這一個作品完美! – mikemike396

5

您的代碼的主要問題是退出您的方法,無需等待所有異步任務完成。您可以使用.Wait()用於這一目的:

public class FileUploadController : ApiController 
{ 
    public void Post() 
    { 
     if (Request.Content.IsMimeMultipartContent()) 
     { 
      var path = HttpContext.Current.Server.MapPath("~/App_Data"); 
      var provider = new MultipartFormDataStreamProvider(path); 
      var readAsMultipartTask = Request.Content.ReadAsMultipartAsync(provider); 
      var continueWithTask = readAsMultipartTask.ContinueWith(t => 
      { 
       if (t.IsFaulted || t.IsCanceled) 
       throw new HttpResponseException(HttpStatusCode.InternalServerError); 
      }); 
      continueWithTask.Wait(); 
     } 
     else 
     { 
      throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted")); 
     } 
    } 
} 

這將使上傳正常工作,但你應該知道,你的方法是打破HTTP協議,因爲你沒有發回的正確上傳的情況下,任何的迴應。你的方法應該是更多這樣的:

public class FileUploadController : ApiController 
{ 
    public async Task<HttpResponseMessage> Post() 
    { 
     if (Request.Content.IsMimeMultipartContent()) 
     { 
      var path = HttpContext.Current.Server.MapPath("~/App_Data"); 
      var provider = new MultipartFormDataStreamProvider(path); 
      await Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t => 
      { 
       if (t.IsFaulted || t.IsCanceled) 
        throw new HttpResponseException(HttpStatusCode.InternalServerError); 
      }); 
      //Here you should return a meaningful response 
      return Request.CreateResponse(HttpStatusCode.OK); 
     } 
     else 
     { 
      throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted")); 
     } 
    } 
} 

(由於使用異步電動機/等待異步任務的同步是由框架處理)

+1

你的解決方案幫了我很多...雖然這個問題並沒有問我,但是非常有幫助......謝謝 –