2012-10-04 83 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

你的解决方案帮了我很多...虽然这个问题并没有问我,但是非常有帮助......谢谢 –