HttpClient and PushStreamContent

I use PushStreamContent with my REST API (ASP.NET Web API) and it works fine. HttpClient can request a ressource and receives an HTTP response before the entire request is processed by the server (the server is still writing to the push stream).

As an HttpClient, you have one little thing to do: use HttpCompletionOption.ResponseHeadersRead.

Now my question is: Can this be any different? From HttpClient -> loading data via push stream into web api?

I implemented it as shown below, but the web api receives the request no earlier than the client closes the stream.

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 is my delegate class:

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

This is necessary for push stream.

Is it possible somehow? HttpClient does not send a request for web api until the last bytes are written to the stream ...

What should I do? Is the problem on the client side or possibly on the /asp.net web api-side server?

Edit: This is an implementation of WriteToStream (but I do not use a file from disk, it uses memystream 'myMemoryStream' (passed in the constructor):

 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 need to do something with: the content of the HttpContent, the context of the TransportContext?

+7
c # asp.net-web-api
source share
2 answers

I found a solution to my problem:

I want to set: httpWebRequest.AllowReadStreamBuffering = false;

HttpClient 4.0 does the default buffering, and you cannot use the AllowReadStreamBuffering property, so you need to use HttpWebRequest directly. (Or you can use HttpClinet 4.5, there is a default "streaming" behavior): http://www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api/ 6. Using HttpClient)

The second problem was the violinist: Fiddler currently only supports response streams, not requests ( Fiddler makes the HttpWebRequest / HttpClient behavior unexpected )

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 ... 
+5
source

Be sure to do requestMessage.Headers.TransferEncodingChunked = true; in your request message ... the reason is that you are not setting this, HttpClient will buffer all the content on the client itself to find out the length of the request content and this is the reason you notice that your web api service is not being called right away when you write to the stream ...

+2
source

All Articles