简体   繁体   English

HttpClient和PushStreamContent

[英]HttpClient and PushStreamContent

I use PushStreamContent with my REST API (ASP.NET Web API) and works great. 我将RESTAPI(ASP.NET Web API)与PushStreamContent一起使用,效果很好。 The HttpClient can request a ressource and gets the HTTP-Response before the complete request is handled by the server (the server still writes to the push-stream). HttpClient可以请求资源,并在服务器处理完整的请求之前获取HTTP-Response(服务器仍然写入推流)。

As HttpClient you have to do one little thing: Use HttpCompletionOption.ResponseHeadersRead. 作为HttpClient,您必须做一件事:使用HttpCompletionOption.ResponseHeadersRead。

Now my question: Is it possible to to this the other way? 现在我的问题是:是否有可能这样做呢? From the HttpClient -> uploading data via a push-stream to the web api? 从HttpClient->通过推送流将数据上传到Web API?

I Implemented it as below, but the web api gets the request not before the client closes the stream. 我实现了如下,但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();

The AsyncStream is my class with the delegate: AsyncStream是我的代表类:

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

This is necessary for the Push-Stream. 这对于Push-Stream是必需的。

Is this possible somehow? 这有可能吗? The HttpClient do not send the request to the web api until the last bytes are written to the stream... 在将最后一个字节写入流之前,HttpClient不会将请求发送到Web api。

What do I have to do? 我需要做什么? Is the problem on the client side or maybe on the server / asp.net web api-side? 问题出在客户端还是服务器/ asp.net Web api端?

Edit: This is the implemenation of WriteToStream (but I do not use a file from disk, is use a memorystream 'myMemoryStream' (passed in the constructor): 编辑:这是WriteToStream的实现(但我不使用磁盘中的文件,而是使用memorystream'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();
    }
}

Maybe I have to do something with: HttpContent content, TransportContext context ? 也许我必须做些事情:HttpContent内容,TransportContext上下文?

I found the solution to my problem: 我找到了解决问题的方法:

I want to set: httpWebRequest.AllowReadStreamBuffering = false; 我要设置:httpWebRequest.AllowReadStreamBuffering = false;

HttpClient 4.0 does buffering by default and you cannot acces the property AllowReadStreamBuffering, so you have to use HttpWebRequest directly. HttpClient 4.0默认情况下会进行缓冲,并且您无法访问属性AllowReadStreamBuffering,因此必须直接使用HttpWebRequest。 (Or you can use HttpClinet 4.5, there is the default behaviour 'streaming') see: http://www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api/ 6. Using HttpClient) (或者您可以使用HttpClinet 4.5,这是默认行为“流式传输”),请参见: http : //www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api / 6.使用HttpClient)

The second problem was fiddler: Fiddler currently only supports streaming of responses and not requests ( Fiddler makes HttpWebRequest/HttpClient behaviour unexpected ) 第二个问题是提琴手:提琴手当前仅支持响应流而不是请求( 提琴手使HttpWebRequest / HttpClient行为出乎意料

The solution that worked for me: 对我有用的解决方案:

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 ...

Make sure to do requestMessage.Headers.TransferEncodingChunked = true; 确保执行requestMessage.Headers.TransferEncodingChunked = true; on your request message...the reason is if you do not set this, HttpClient would buffer the entire content at the client itself in order to figure out the Content-length of the request and this is the reason you are noticing your web api service not being invoked immediately as you are writing to the stream... 在您的请求消息上...原因是如果您未设置此项,则HttpClient会在客户端本身缓冲整个内容,以便找出请求的Content-length,这就是您注意到Web api的原因正在写入流时,服务不会立即被调用...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM