Загружать файлы в локальное хранилище с помощью MvvmCross

В настоящее время я пытаюсь загрузить файлы с сервера, используя веб-службы в переносной библиотеке. Для каждого файла я делаю так:

WebRequest request = WebRequest.Create("http://localhost:49364/" + url);

 request.BeginGetResponse((aResult) =>
 {
      var retour = aResult.AsyncState as WebRequest;
      WebResponse reponse = retour.EndGetResponse(aResult);
      callback(reponse);
 }, request);

В моем методе обратного вызова я делаю следующее:

byte[] bytes;
string currentFileName = fileName;
string categorie = currentFileName.Split('/').ElementAt(0);
string dir = currentFileName.Split('/').ElementAt(1);

using (var reader = new BinaryReader(reponse2.GetResponseStream()))
{
    bytes = new byte[reponse2.ContentLength];
    reader.Read(bytes, 0, (int)reponse2.ContentLength);
}
fileService.EnsureFolderExists(categorie);
fileService.EnsureFolderExists(fileService.PathCombine(categorie, dir));
fileService.WriteFile(currentFileName, bytes);

Я получаю весь файл в виде байтового массива. Но с WinRT запись файла быстро прекращается, и мой локальный файл не завершен. Если я попытаюсь загрузить только один файл, запись также остановится. Но если я попробую использовать Silverlight (я расширил MvvmCross до Silverlight), написание будет завершено. Я еще не тестировал MonoDroid et MonoTouch.

Итак, мой вопрос: почему письмо прекращается?


person Titecarma    schedule 05.11.2012    source источник


Ответы (2)


Я просмотрел код для WriteFile в MvxBlockingWinRTFileStoreService.cs, и я не вижу очевидной ошибки.

Чтобы проверить это, я только что написал быстрое автономное тестовое приложение WinRT с использованием https://gist.github.com/4016898.

Это отлично сохраняет файл домашней страницы Bing размером 37 КБ. Это также работает на вашем сервере?

После этого теста я предполагаю, что, возможно, в вашем коде веб-передачи есть какая-то ошибка - возможно, даже в службе localhost. Однако все же возможно, что ошибка в сохранении StorageFile.

Некоторые вопросы:

  • Можете ли вы добавить дополнительную трассировку, чтобы узнать длину буфера данных, сообщаемую на каждом этапе загрузки?

  • Можете ли вы адаптировать приведенную выше простую тестовую оснастку, чтобы она показывала те же результаты?


Один из возможных кандидатов:

Вы используете ContentLength в качестве длины потока? Вы уверены, что это правильная длина?

например если у вас включено сжатие GZip, ContentLength предоставит вам длину переданных сжатых данных, а не длину самих данных - см. https://stackoverflow.com/questions/3819280/content-length-when-using-http-compress

Чем больше я думаю об этом, тем больше для меня это имеет смысл - Silverlight будет использовать стек браузера, который будет иметь разные заголовки приема HTTP по сравнению со стеком WinRT.


Хорошие новости заключаются в том, что async / await скоро появятся в MonoTouch и MonoDroid - и когда они появятся, я постараюсь сделать все файловые API доступными как async и await.

person Stuart    schedule 05.11.2012

Стюарт,

Во-первых, спасибо за ответ!

Я попробовал ваш пример и адаптировался к моему случаю (загружал файлы с сервера через веб-сервис), и сначала все работало. Все файлы загружены правильно. Но когда я добавил изображения для загрузки, у меня возникла та же проблема. Файлы изображений И текстовые файлы не являются полными.

Но, посмотрев на код вашего примера, я нашел решение, подумав, что я действительно не понимаю, в чем проблема.

Для написания работ заменил (в своем методе обратного вызова):

...

using (var reader = new BinaryReader(reponse2.GetResponseStream()))
{
    bytes = new byte[reponse2.ContentLength];
    reader.Read(bytes, 0, (int)reponse2.ContentLength);
}
...
fileService.WriteFile(currentFileName, bytes);

этим :

...

var mem = new MemoryStream();
using (var stream = reponse2.GetResponseStream())
{
        stream.CopyTo(mem);
}
mem.Seek(0L, SeekOrigin.Begin);
...
fileService.WriteFile(currentFileName, mem.ToArray());

Не знаю почему, но работает! (Если вы знаете, почему это работает, мне интересно)

Итак, спасибо за вашу помощь!

person Titecarma    schedule 05.11.2012
comment
см. мой ответ - он выделен жирным шрифтом - ContentLength - это не длина распакованного потока. PS Мы хотим, чтобы ваш порт Silverlight был публичным :) - person Stuart; 05.11.2012
comment
Стюарт, я пришел к вам по адаптации Mvvmcross Silverlight. Могу я узнать ваш адрес электронной почты, чтобы отправить вам код? Я не использую GitHub ... А когда у вас есть код, у меня к вам вопрос по поводу утечки памяти;) Спасибо! - person Titecarma; 28.11.2012
comment
Лучшая контактная информация находится на slodge.blogspot.co.uk/p /if-youve-got-questions.html - person Stuart; 28.11.2012
comment
хотя, если вы нажмете на мое имя в StackOverflow, тогда в нем также есть некоторые подсказки;) - person Stuart; 28.11.2012