HttpClient и PushStreamContent

Я использую PushStreamContent с моим REST API (ASP.NET Web API) и отлично работает. HttpClient может запросить ressource и получает HTTP-ответ до того, как полный запрос будет обработан сервером (сервер все еще записывает в push-поток).

как HttpClient вы должны сделать одну маленькую вещь: использовать HttpCompletionOption.ResponseHeadersRead.

Теперь мой вопрос: Можно ли к этому другим путем? Из HttpClient - > загрузка данных через push-поток в веб-api?

я реализовал его, как показано ниже, но веб-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 не отправляет запрос в веб-api, пока последние байты не будут записаны в поток...

что я должен сделать? Проблема на стороне клиента или возможно, на сервере / asp.net веб-api-сторона?

изменить: Это имплементация 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();
    }
}

может быть, мне нужно что-то сделать с содержимым HttpContent, контекстом TransportContext ?

2 ответов


Я нашел решение своей проблемы:

Я хочу установить: httpWebRequest.AllowReadStreamBuffering = false;

HttpClient 4.0 выполняет буферизацию по умолчанию, и вы не можете получить доступ к свойству AllowReadStreamBuffering, поэтому вам нужно использовать HttpWebRequest напрямую. (Или вы можете использовать HttpClinet 4.5, есть поведение по умолчанию "потоковое") см.:http://www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api/ 6. С помощью С помощью HttpClient)

второй проблемой был fiddler: Fiddler в настоящее время поддерживает только потоковую передачу ответов, а не запросов (Fiddler делает поведение 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 ...

обязательно сделайте requestMessage.Headers.TransferEncodingChunked = true; на вашем сообщении запроса...причина в том, что если вы не установите это, HttpClient будет буферизировать весь контент на самом клиенте, чтобы выяснить длину контента запроса, и это причина, по которой вы замечаете, что ваша служба веб-api не вызывается сразу, когда вы пишете в поток...