2013-07-05 29 views
1

使用VS 2012,ASP.NET Web API 4.0,4.0版的Web API客户端库。
我创建了一个“hello world”控制器,并且获得了简单的get/post工作。但是,我无法发布文件。无法从HttpClient发布文件到ASP.NET Web API

我正在通过HttpClient客户端访问服务,但无法使用简单的HTML页面来工作(发布文件),无论我尝试了什么。但是,这有它自己的问题(并且内容总是碰到了IsMimeMultipartContent,而我的HttpClient没有);我只想得到一个HttpClient现在的工作。客户端流在文件中的罚款(我可以看到长度是好的),但在服务器上,ReadAsStreamAsync中的流的长度为0.此外,HttpContext.Current.Request.Files计数为0(即使当从HTML文件发布)。

这里的控制器:

public class ImportController : ApiController 
{ 

    public HttpResponseMessage Post() 
    { 
     WriteFile(HttpContext.Current.Server.MapPath("~/killme.xml")); 
     return new HttpResponseMessage(HttpStatusCode.Accepted); 
    } 

    private void WriteFile(string filePath) 
    { 
     Request.Content.ReadAsStreamAsync().ContinueWith(task => 
     { 
      try 
      { 
       var requestStream = task.Result; 
       var fileStream = File.Create(filePath); 
       requestStream.CopyTo(fileStream); 
       fileStream.Close(); 
       requestStream.Close(); 
      } 
      catch 
      { 
       ; // TBD 
      } 
     }); 
    } 

} 

下面是客户端:

var client = new HttpClient(); 
client.PostAsync("http://localhost:52800/api/Import", ReadFile()).ContinueWith((task) => 
{ 
    Console.WriteLine(task.Result.StatusCode.ToString()); 
    client.Dispose(); 
}); 

private static StreamContent ReadFile() 
{ 
    var fileBytes = File.ReadAllBytes(@"C:\temp\killme.xml"); 
    var ms = new MemoryStream(fileBytes.Length); 
    ms.Write(fileBytes, 0, fileBytes.Length); 
    // Can't put this in using; don't know how to dispose 
    return new StreamContent(ms); 
} 

回答

1

我认为你唯一的错误是忘记将它传递给StreamContent之前重置内存流的位置。但是,我更愿意创建一个专门用于处理发送文件的派生HttpContent类。

有了这个类代码会是什么样子,

var client = new HttpClient(); 
var content = new FileContent(@"C:\temp\killme.xml"); 
client.PostAsync("http://localhost:52800/api/Import", content).ContinueWith((task) => 
{ 
    Console.WriteLine(task.Result.StatusCode.ToString()); 
    client.Dispose(); 
}); 

例如

public class FileContent : HttpContent 
    { 
     private const int DefaultBufferSize = 1024 * 64; 
     private readonly string _fileName; 
     private readonly FileInfo _fileInfo; 

     public FileContent(string fileName) 
     { 
      if (string.IsNullOrWhiteSpace(fileName)) 
      { 
       throw new ArgumentNullException("fileName"); 
      } 
      _fileInfo = new FileInfo(fileName); 
      if (!_fileInfo.Exists) 
      { 
       throw new FileNotFoundException(string.Empty, fileName); 
      } 

      _fileName = fileName; 

     } 

     protected override bool TryComputeLength(out long length) 
     { 
      length = _fileInfo.Length; 
      return true; 
     } 

     private FileStream _FileStream; 
     protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 
     { 
      _FileStream = new FileStream(_fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 
             DefaultBufferSize, 
             FileOptions.Asynchronous | FileOptions.SequentialScan); 

      _FileStream.CopyTo(stream); 
      var tcs = new TaskCompletionSource<object>(); 
      tcs.SetResult(null); 
      return tcs.Task; 

     } 

     protected override void Dispose(bool disposing) 
     { 
      if (_FileStream != null) 
      { 
       _FileStream.Dispose(); 
       _FileStream = null; 
      } 
      base.Dispose(disposing); 
     } 
    } 
} 
+0

将我的数据流重置为0不起作用,但您的代码确实有效;小记:结尾有额外的卷曲。 – dudeNumber4

+0

重置我的流确实可行,我很困惑,我无法多次运行任何一种方法(除非我重新启动IIS Express)。在你的代码中没有任何东西是没有处理的;不知道是什么让第二次运行时请求流长度为0 – dudeNumber4

相关问题