Загрузить количество байтов из веб-источника

Я пытаюсь загрузить несколько байтов из веб-источника, используя HttpWebRequest (может быть любым другим способом - я пробовал WebRequest, HttpClient...) в среде выполнения Windows Phone 8.1 - полный код:

private async void Download1000_Click(object sender, RoutedEventArgs e)
{
    Debug.WriteLine("Download Started");
    HttpWebRequest longRequest = (HttpWebRequest)WebRequest.Create(new Uri(@"http://s3.amazonaws.com/dnr/dotnetrocks_0986_enterprise_sharepoint.mp3"));
    longRequest.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString(); // prevent caching the whole file
    longRequest.AllowReadStreamBuffering = false;
    using (WebResponse myResponse = await longRequest.GetResponseAsync())
    using (Stream myStream = myResponse.GetResponseStream())
    {
        int bytesRead = 0;
        byte[] myBuffer = new byte[1000];
        Stopwatch newWatch = new Stopwatch();
        newWatch.Start();
        while ((bytesRead = await myStream.ReadAsync(myBuffer, 0, 1000)) > 0)
            Debug.WriteLine(bytesRead.ToString() + " bytes read. Elapsed time: " + newWatch.Elapsed.TotalSeconds.ToString("0.000000") + " seconds");
    }
    Debug.WriteLine("Download Finished");
}

Проблема - код работает, но ОС почему-то не дает прочитать небольшое количество байт (даже я отключил AllowReadStreamBuffering) - вроде скачивает файл целиком в какой-то кеш(?) и потом запускает while loop. Это выглядит так:

withSomeCache

Как видите - первая сумма байт появляется через 22 секунды - файл скачался целиком. Наоборот, когда я создал тот же код (скопировал-вставил) на Windows Phone 8.1 Silverligh и запустил на том же устройстве - он работает как надо:

без кэша

Есть ли способ загрузить количество байтов во время выполнения WP8.1 без предварительной загрузки всего файла?


person Romasz    schedule 23.05.2014    source источник
comment
Не уверен, что это что-то изменит, но вы можете попробовать с HttpClient: msdn.microsoft.com/en-us/library/windows/apps/   -  person Kevin Gosse    schedule 23.05.2014
comment
После дополнительных исследований - я пробовал с HttpClient с MaxResponseContentBufferSize, через IBuffer, с параметрами InputStream Partial, и он всегда ведет себя одинаково. Думал, может что-то пропустил.   -  person Romasz    schedule 24.05.2014


Ответы (2)


Вот крайняя идея - используйте сокеты! Это очень не круто, я знаю.

Если то, что вам нужно, не является сверхсложным, вы можете что-то смешать, используя эти два: библиотека HTTP-сокетов .NET и TcpClient для WP. Недавно мне это понадобилось для приложения Windows Phone 8.0, поэтому я использовал эти библиотеки, и все работает нормально.

Редактировать – демонстрационный проект

Вот демонстрационный проект, который делает то, что я только что предложил. В этом нет ничего эпического, но, похоже, это помогает. Если вам не нужно что-то слишком сложное, оно должно работать нормально.

Оффтоп - зачем мне сокеты

Недавно у меня возникла проблема со всеми другими доступными опциями для http-запросов — всем им нужно, чтобы поток пользовательского интерфейса был свободен для работы (по крайней мере, в Windows Phone, не уверен насчет WinRT). То есть — они на самом деле что-то делают в потоке пользовательского интерфейса, даже если вы используете их из другого потока. И в целом это нормально... за исключением того, что в моей ситуации мне действительно нужно было заблокировать поток пользовательского интерфейса.

person yasen    schedule 23.05.2014
comment
Спасибо за информацию. Я постараюсь следовать вашим предложениям и провести небольшое исследование - думаю, это, вероятно, займет у меня некоторое время. Тем не менее, я все еще ищу ответ, почему упомянутые методы перестали работать на WinRT. Кажется, что AllowReadStreamBuffering всегда верно. - person Romasz; 23.05.2014
comment
Я надеюсь, что вы могли бы сделать это более простым способом (должен быть), но я заметил, что вы уже пробовали кое-что, поэтому я решил дать идею, которая может помочь, если больше ничего не поможет. Я могу поискать более простое решение, когда у меня будет немного свободного времени. :) - person yasen; 23.05.2014
comment
Возможно, это сработает, поскольку это другой подход, но требует много работы - эти библиотеки предназначены для WP8.0, а не для среды выполнения. Самое странное, что во всех описаниях написано, что это должно работать — и работает, но только в Silverlight. Спасибо :) - person Romasz; 24.05.2014
comment
@Romasz Вы нашли лучшее решение? Вы пробовали мою идею? Вам это еще нужно? - person yasen; 29.05.2014
comment
Не пробовал (нет времени). Кажется, я знаю, в чем проблема - в WP8.1 передача идет через "Контроль данных" - он проверяет, используете ли вы роуминг, превысили лимит и т.д. Я начал использовать BackgroundTransfer, который, похоже, имеет встроенную совместимость с «Data Sense». Работает довольно хорошо и не имеет столько ограничений, как в WP8.0. Конечно, это не отвечает на вопрос, почему вы не можете прочитать несколько байтов из веб-источника перед загрузкой всего файла. - person Romasz; 29.05.2014
comment
@Romasz Я тоже изучил это, но не смог найти ни способа заставить его работать, ни хорошего объяснения, почему это так работает. Мне это кажется ошибкой. Вот демонстрационный проект того, что я упомянул, кстати, если вам все еще нужно загрузить несколько байт. Обратите внимание, что это может быть не идеально, это немного хакерски, но, похоже, работает. - person yasen; 30.05.2014
comment
Вау - спасибо, очень хорошая работа. Я думаю, что нам придется ждать следующего выпуска SDK - это тоже выглядит как ошибка/недоразумение. Я бы предпочел не писать собственный hhtpclient в своем проекте;) Я также думаю, что вы должны поместить ссылку в свой ответ - это действительно хороший пример. - person Romasz; 30.05.2014
comment
@Romasz Я положил ссылку в ответ. Надеюсь, кто-то найдет это полезным. :) О, и я бы предпочел избежать этого, если это возможно. Но в нашем случае других вариантов не было. Мы использовали версию WP8.0 некоторое время (только в одном месте), и она работает нормально. ;) - person yasen; 30.05.2014

Это ошибка в SDK. Сообщили команде Microsoft по электронной почте и получили подтверждение от одного из их инженеров. Надеюсь в следующем релизе исправят...

person cotaku39    schedule 31.05.2014