1

使用 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 );
}
4

1 回答 1

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);
        }
    }
}
于 2013-07-06T00:57:05.080 回答