无法从HttpClient将文件发布到ASP.NET Web API

时间:2013-07-05 22:25:02

标签: asp.net-web-api

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

我正在通过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 个答案:

答案 0 :(得分: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();
} );

E.g。

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