Note that there are some explanatory texts on larger screens.

plurals
  1. PO"Where are my bytes?" or Investigation of file length traits
    text
    copied!<p>This is a continuation of my question about <a href="https://stackoverflow.com/questions/14602186/download-file-in-chunks-windows-phone">downloading files in chunks</a>. The explanation will be quite big, so I'll try to divide it to several parts.</p> <p><strong>1) What I tried to do?</strong></p> <p>I was creating a download manager for a Window-Phone application. First, I tried to solve the problem of downloading large files (the explanation is in the previous question). No I want to add <em>"resumable download"</em> feature.</p> <p><strong>2) What I've already done.</strong></p> <p>At the current moment I have a well-working download manager, that allows to outflank the Windows Phone RAM limit. The plot of this manager, is that it allows to download small chunks of file consequently, using HTTP Range header.</p> <p>A fast explanation of how it works:</p> <p>The file is downloaded in chunks of constant size. Let's call this size <em>"delta"</em>. After the file chunk was downloaded, it is saved to local storage (hard disk, on WP it's called Isolated Storage) in Append mode (so, the downloaded byte array is always added to the end of the file). After downloading a single chunk the statement</p> <pre><code>if (mediaFileLength &gt;= delta) // mediaFileLength is a length of downloaded chunk </code></pre> <p>is checked. If it's true, that means, there's something left for download and this method is invoked recursively. Otherwise it means, that this chunk was last, and there's nothing left to download.</p> <p><strong>3) What's the problem?</strong></p> <p>Until I used this logic at one-time downloads (By one-time I mean, when you start downloading file and wait until the download is finished) that worked well. However, I decided, that I need <em>"resume download"</em> feature. <strong>So, the facts:</strong></p> <p><strong>3.1)</strong> I know, that the file chunk size is a constant.</p> <p><strong>3.2)</strong> I know, when the file is completely downloaded or not. (that's a indirect result of my app logic, won't weary you by explanation, just suppose, that this is a fact)</p> <p>On the assumption of these two statements I can prove, that the number of downloaded chunks is equal to <strong>(CurrentFileLength)/delta</strong>. Where <em>CurrentFileLenght</em> is a size of already downloaded file in bytes.</p> <p>To resume downloading file I should simply set the required headers and invoke download method. That seems logic, isn't it? And I tried to implement it:</p> <pre><code> // Check file size using (IsolatedStorageFileStream fileStream = isolatedStorageFile.OpenFile("SomewhereInTheIsolatedStorage", FileMode.Open, FileAccess.Read)) { int currentFileSize = Convert.ToInt32(fileStream.Length); int currentFileChunkIterator = currentFileSize / delta; } </code></pre> <p>And what I see as a result? The downloaded file length is equal to <strong>2432000</strong> bytes (<strong>delta is 304160</strong>, Total file size is about <strong>4,5 MB</strong>, we've downloaded only half of it). So the result is approximately <strong>7,995</strong>. (it's actually has long/int type, so it's 7 and should be 8 instead!) Why is this happening? Simple math tells us, that the file length should be <strong>2433280</strong>, so the given value is very close, but not equal.</p> <p>Further investigations showed, that all values, given from the <code>fileStream.Length</code> are not accurate, but all are close.</p> <p><strong>Why is this happening?</strong> I don't know precisely, but perhaps, the .Length value is taken somewhere from file metadata. Perhaps, such rounding is normal for this method. Perhaps, when the download was interrupted, the file wasn't saved totally...(no, that's real fantastic, it can't be)</p> <p>So the problem is set - it's <strong>"How to determine number of the chunks downloaded"</strong>. Question is how to solve it.</p> <p><strong>4) My thoughts about solving the problem.</strong></p> <p>My first thought was about using maths here. Set some <em>epsilon-neiborhood</em> and use it in <code>currentFileChunkIterator = currentFileSize / delta;</code> statement. But that will demand us to remember about type I and type II errors (or false alarm and miss, if you don't like the statistics terms.) Perhaps, there's nothing left to download. Also, I didn't checked, if the difference of the provided value and the true value is supposed to grow permanently or there will be cyclical fluctuations. With the small sizes (about 4-5 MB) I've seen only growth, but that doesn't prove anything.</p> <p>So, I'm asking for help here, as I don't like my solution.</p> <p><strong>5) What I would like to hear as answer:</strong></p> <p><em>What causes the difference between real value and received value?</em></p> <p><s><em>Is there a way to receive a true value?</em></s></p> <p><s><em>If not, is my solution good for this problem?</em></s></p> <p><s><em>Are there other better solutions?</em></s></p> <p>P.S. I won't set a Windows-Phone tag, because I'm not sure that this problem is OS-related. I used the Isolated Storage Tool to check the size of downloaded file, and it showed me the same as the received value(I'm sorry about Russian language at screenshot): </p> <p><img src="https://i.stack.imgur.com/UJ77c.png" alt="File size is wrong image"></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload