11

我将 PushStreamContent 与我的 REST API (ASP.NET Web API) 一起使用,效果很好。HttpClient 可以在服务器处理完整请求之前请求资源并获取 HTTP-Response(服务器仍然写入推送流)。

作为 HttpClient,您必须做一件小事:使用 HttpCompletionOption.ResponseHeadersRead。

现在我的问题是:是否有可能以另一种方式做到这一点?从 HttpClient -> 通过推送流将数据上传到 Web api?

我按如下方式实现它,但 web api 不会在客户端关闭流之前获取请求。

         var asyncStream = new AsyncStream(fs);
         PushStreamContent streamContent = new PushStreamContent(asyncStream.WriteToStream);
         content.Add(streamContent);

         HttpResponseMessage response = await c.SendAsync(new HttpRequestMessage(new HttpMethod("POST"), "http://localhost/...") { Content = content }, HttpCompletionOption.ResponseHeadersRead);

         response.EnsureSuccessStatusCode();

AsyncStream 是我的委托类:

public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)

这对于 Push-Stream 是必需的。

这有可能吗?在最后一个字节被写入流之前,HttpClient 不会将请求发送到 web api...

我需要做什么?问题是在客户端还是在服务器/asp.net web api端?

编辑:这是 WriteToStream 的实现(但我不使用磁盘中的文件,而是使用内存流'myMemoryStream'(在构造函数中传递):

public void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
{
    try
    {
        var buffer = new byte[4096];

        using (var stream = myMemoryStream)
        {
            var bytesRead = 1;

            while (bytesRead > 0)
            {
                bytesRead = video.Read(buffer, 0, buffer.Length);
                outputStream.Write(buffer, 0, bytesRead);
            }
        }
    }
    catch (HttpException ex)
    {
        return;
    }
    finally
    {
        outputStream.Close();
    }
}

也许我必须做点什么:HttpContent 内容,TransportContext 上下文?

4

2 回答 2

5

我找到了解决问题的方法:

我要设置:httpWebRequest.AllowReadStreamBuffering = false;

HttpClient 4.0 默认做缓冲,不能访问 AllowReadStreamBuffering 属性,所以必须直接使用 HttpWebRequest。(或者你可以使用HttpClinet 4.5,有默认行为'streaming')见: http: //www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api / 6. 使用HttpClient)

第二个问题是提琴手:提琴手目前只支持响应流而不是请求(提琴手使 HttpWebRequest/HttpClient 行为意外

对我有用的解决方案:

HttpWebRequest httpWebRequest = HttpWebRequest.Create(...)
httpWebRequest.Method = "POST";
         httpWebRequest.Headers["Authorization"] = "Basic " + ...;
         httpWebRequest.PreAuthenticate = true;
         httpWebRequest.AllowWriteStreamBuffering = false;
         httpWebRequest.AllowReadStreamBuffering = false;
         httpWebRequest.ContentType = "application/octet-stream";
         Stream st = httpWebRequest.GetRequestStream();
st.Write(b, 0, b.Length);
st.Write(b, 0, b.Length);
//...
         Task<WebResponse> response = httpWebRequest.GetResponseAsync();

         var x = response.Result;
         Stream resultStream = x.GetResponseStream();
//... read result-stream ...
于 2014-08-29T12:31:39.653 回答
4

确保requestMessage.Headers.TransferEncodingChunked = true;对您的请求消息执行...原因是如果您不设置此选项,HttpClient 将在客户端本身缓冲整个内容,以便确定请求的内容长度,这就是您的原因注意到您在写入流时没有立即调用您的 Web api 服务...

于 2014-08-21T15:28:07.727 回答