Это продолжение моего вопроса о загрузке файлов в куски. Объяснение будет довольно большим, поэтому я попытаюсь разделить его на несколько частей.
1) Что я пытался сделать?
Я создавал диспетчер загрузки для приложения Window-Phone. Во-первых, я попытался решить проблему загрузки большие файлы (объяснение в предыдущем вопросе). Нет. Я хочу добавить функцию "возобновляемой загрузки".
2) Что я уже сделал.
В настоящий момент у меня есть хорошо работающий менеджер загрузок, который позволяет обойти ограничение по ОЗУ Windows Phone. Сюжет этого менеджера заключается в том, что он позволяет загружать небольшие фрагменты файла, используя заголовок HTTP Range.
Быстрое объяснение того, как это работает:
Файл загружается в куски постоянного размера. Позвольте называть этот размер "delta". После загрузки фрагмента файла, он сохраняется в локальном хранилище (жесткий диск, на WP он называется изолированным хранилищем) в режиме добавления (так что загруженный массив байтов всегда добавляется в конец файла). После загрузки одного фрагмента оператор
if (mediaFileLength >= delta) // mediaFileLength is a length of downloaded chunk
. Если это правда, то означает, что что-то осталось для загрузки, и этот метод вызывается рекурсивно. В противном случае это означает, что этот кусок был последним, и загрузить его не удавалось.
3) Какая проблема?
До тех пор, пока я не использовал эту логику при одноразовых загрузках (в одно время я имею в виду, когда вы начинаете загрузку файла и дождитесь завершения загрузки) это сработало хорошо. Однако я решил, что мне нужно "возобновить загрузку". Итак, факты:
3.1) Я знаю, что размер куска файла является константой.
3.2) Я знаю, когда файл полностью загружен или нет. (что косвенным результатом моей логики приложения, не устанет от вас объяснением, просто предположите, что это факт)
В предположении этих двух утверждений я могу доказать, что количество загруженных кусков равно (CurrentFileLength)/дельта. Где CurrentFileLenght - размер уже загруженного файла в байтах.
Чтобы возобновить загрузку файла, я должен просто установить необходимые заголовки и вызвать метод загрузки. Это кажется логикой, не так ли? И я попытался его реализовать:
// Check file size
using (IsolatedStorageFileStream fileStream = isolatedStorageFile.OpenFile("SomewhereInTheIsolatedStorage", FileMode.Open, FileAccess.Read))
{
int currentFileSize = Convert.ToInt32(fileStream.Length);
int currentFileChunkIterator = currentFileSize / delta;
}
И что я вижу в результате? Длина загруженного файла равна байту 2432000 ( delta = 304160; общий размер файла 4,5 МБ, мы скачали только половина его). Таким образом, результат примерно 7,995. (на самом деле он имеет длинный/int-тип, поэтому он 7 и должен быть 8 вместо!) Почему это происходит? Простая математика говорит нам, что длина файла должна быть 2433280, поэтому данное значение очень близко, но не равно.
Дальнейшие исследования показали, что все значения, заданные изfileStream.Length
, неточны, но все близки.
Почему это происходит? Я точно не знаю, но, возможно, значение .Length берется где-то из метаданных файла. Возможно, такое округление является нормальным для этого метода. Возможно, когда загрузка была прервана, файл не был полностью сохранен... (нет, это действительно фантастично, этого не может быть)
Итак, проблема установлена - это "Как определить количество загруженных кусков" . Вопрос в том, как его решить.
4) Мои мысли о решении проблемы.
Моя первая мысль заключалась в том, чтобы использовать математику здесь. Установите некоторое epsilon-neiborhood и используйте его в инструкции currentFileChunkIterator = currentFileSize / delta;
. Но это потребует, чтобы мы помнили о ошибках типа я и типа II (или ложных тревогах и промахах, если вам не нравятся термины статистики.) Возможно, ничего не осталось для загрузки. Кроме того, я не проверял, если предполагается, что разница предоставленного значения и истинного значения будет постоянно расти или будут циклические колебания. С небольшими размерами (около 4-5 МБ) я видел только рост, но это ничего не доказывает.
Итак, я прошу о помощи здесь, так как мне не нравится мое решение.
5) Что я хотел бы услышать в качестве ответа:
Что вызывает разницу между реальным значением и полученным значением?
Есть ли способ получить истинное значение?
Если это не так, мое решение подходит для этой проблемы?
Существуют ли другие лучшие решения?
P.S. Я не буду устанавливать тег Windows-Phone, потому что я не уверен, что эта проблема связана с ОС. Я использовал изолированный инструмент хранения чтобы проверить размер загруженного файла, и он показал мне то же самое, что и полученное значение (я сожалею о русском языке на снимке экрана):