Asp.net web api Can';t从HttpClient向ASP.NET Web API发布文件

Asp.net web api Can';t从HttpClient向ASP.NET Web API发布文件,asp.net-web-api,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工作。文件中的客户端流很

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

我认为您唯一的错误是在将内存流传递给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();
} );
例如

公共类FileContent:HttpContent
{
private const int DefaultBufferSize=1024*64;
私有只读字符串\u文件名;
私有只读文件信息_FileInfo;
公共文件内容(字符串文件名)
{
if(string.IsNullOrWhiteSpace(文件名))
{
抛出新的ArgumentNullException(“文件名”);
}
_fileInfo=新的fileInfo(文件名);
如果(!\u fileInfo.Exists)
{
抛出新的FileNotFoundException(string.Empty,fileName);
}
_fileName=文件名;
}
受保护的覆盖布尔TryComputeLength(out long length)
{
长度=_fileInfo.length;
返回true;
}
私有文件流\u文件流;
受保护的重写任务SerializeToStreamAsync(流、TransportContext上下文)
{
_FileStream=新FileStream(_fileName,FileMode.Open,FileAccess.Read,FileShare.ReadWrite,
默认缓冲区大小,
FileOptions.Asynchronous | FileOptions.SequentialScan);
_CopyTo(流);
var tcs=new TaskCompletionSource();
tcs.SetResult(空);
返回tcs.Task;
}
受保护的覆盖无效处置(布尔处置)
{
如果(_FileStream!=null)
{
_Dispose();
_FileStream=null;
}
基地。处置(处置);
}
}
}

我认为您唯一的错误是在将内存流传递给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();
} );
例如

公共类FileContent:HttpContent
{
private const int DefaultBufferSize=1024*64;
私有只读字符串\u文件名;
私有只读文件信息_FileInfo;
公共文件内容(字符串文件名)
{
if(string.IsNullOrWhiteSpace(文件名))
{
抛出新的ArgumentNullException(“文件名”);
}
_fileInfo=新的fileInfo(文件名);
如果(!\u fileInfo.Exists)
{
抛出新的FileNotFoundException(string.Empty,fileName);
}
_fileName=文件名;
}
受保护的覆盖布尔TryComputeLength(out long length)
{
长度=_fileInfo.length;
返回true;
}
私有文件流\u文件流;
受保护的重写任务SerializeToStreamAsync(流、TransportContext上下文)
{
_FileStream=新FileStream(_fileName,FileMode.Open,FileAccess.Read,FileShare.ReadWrite,
默认缓冲区大小,
FileOptions.Asynchronous | FileOptions.SequentialScan);
_CopyTo(流);
var tcs=new TaskCompletionSource();
tcs.SetResult(空);
返回tcs.Task;
}
受保护的覆盖无效处置(布尔处置)
{
如果(_FileStream!=null)
{
_Dispose();
_FileStream=null;
}
基地。处置(处置);
}
}
}

将我的流重置为0不起作用,但您的代码起作用;小提示:结尾有额外的卷曲。重置我的流确实有效,我很困惑,因为我不能多次运行这两个方法(除非我重新启动IIS Express)。(在您的代码中)没有任何内容未被屏蔽;不知道第二次运行时请求流长度为0的原因…将我的流重置为0不起作用,但您的代码起作用;小提示:结尾有额外的卷曲。重置我的流确实有效,我很困惑,因为我不能多次运行这两个方法(除非我重新启动IIS Express)。(在您的代码中)没有任何内容未被屏蔽;不知道第二次运行时请求流长度为0的原因。。。