HttpClient и PushStreamContent

Я использую PushStreamContent с моим REST API (ASP.NET Web API) и прекрасно работает. HttpClient может запросить ресурс и получает 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 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?

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

Другие вопросы по тегам