这是我关于以块下载文件的问题的延续。解释会很大,所以我会尝试将它分成几个部分。
1)我试图做什么?
我正在为 Window-Phone 应用程序创建下载管理器。首先,我尝试解决下载大文件的问题(解释在上一个问题中)。不,我想添加“可恢复下载”功能。
2)我已经做了什么。
目前我有一个运行良好的下载管理器,它允许绕过 Windows Phone RAM 限制。这个管理器的情节是,它允许使用 HTTP Range 标头下载小块文件。
快速解释它的工作原理:
该文件以恒定大小的块下载。我们称这个大小为“delta”。文件块下载后,以追加模式保存到本地存储(硬盘,在 WP 上称为独立存储)(因此,下载的字节数组始终添加到文件末尾)。下载单个块后,语句
if (mediaFileLength >= delta) // mediaFileLength is a length of downloaded chunk
被检查。如果它是真的,那意味着,还有一些东西要下载,并且这个方法被递归调用。否则,这意味着这个块是最后一个,并且没有任何东西可以下载。
3)有什么问题?
直到我在一次性下载中使用了这个逻辑(我的意思是一次性,当你开始下载文件并等到下载完成时)效果很好。但是,我决定,我需要“恢复下载” 功能。所以,事实:
3.1)我知道,文件块大小是一个常数。
3.2)我知道,文件何时完全下载。(这是我的应用程序逻辑的间接结果,不会让你厌烦解释,只是假设这是事实)
在这两个陈述的假设下,我可以证明,下载的块数等于 (CurrentFileLength)/delta。其中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字节(增量为 304160,总文件大小约为4.5 MB,我们只下载了一半)。所以结果大约是7,995。(它实际上是 long/int 类型,所以它是 7,应该是 8!)为什么会这样?简单的数学告诉我们,文件长度应该是2433280,所以给定的值非常接近,但不相等。
进一步的调查表明,从 给出的所有值fileStream.Length
都不准确,但都接近。
为什么会这样?我不确切知道,但也许 .Length 值是从文件元数据中获取的。也许,这种舍入对于这种方法是正常的。也许,当下载被中断时,文件并没有完全保存……(不,那真是太棒了,不可能)
所以问题就解决了——它是“如何确定下载的块数”。问题是如何解决它。
4)我对解决问题的想法。
我的第一个想法是在这里使用数学。设置一些epsilon-neiborhoodcurrentFileChunkIterator = currentFileSize / delta;
并在语句中使用它。但这将要求我们记住类型 I 和类型 II 错误(或误报和错过,如果您不喜欢统计术语)。也许,没有什么可下载的了。另外,我没有检查提供的值和真实值的差异是否应该永久增长或者会有周期性波动。对于小尺寸(大约 4-5 MB),我只看到了增长,但这并不能证明什么。
所以,我在这里寻求帮助,因为我不喜欢我的解决方案。
5)我想听到的答案:
是什么导致了实际价值和收到的价值之间的差异?
有没有办法获得真正的价值?
如果不是,我的解决方案对这个问题有好处吗?
还有其他更好的解决方案吗?
PS 我不会设置 Windows-Phone 标签,因为我不确定这个问题是否与操作系统相关。我使用独立存储工具检查下载文件的大小,它显示的值与收到的值相同(对于屏幕截图中的俄语,我很抱歉):