Downloading large files with AFNetworking
Solution 1
I have no problems with the setDownloadProgressBlock in AFNetworking.
The wiki explains how to track download progress: https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ
For progress tracking you don't need the bytesRead
(number of bytes written in a particular callback).
Example code:
[downloadoperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
float progress = ((float)totalBytesRead) / totalBytesExpectedToRead;
self.progressView.progress = progress;
}];
Solution 2
phix23 answered to my initial question, so there is really no problem with progress block. I'm answering to my edit.
When success block in
-[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]
is called, I can compare the number of bytes downloaded with the number of bytes expected to download (it is not very hard to implement in code). If the number of downloaded bytes is smaller - I can continue file download from place where it was interrupted. To do this, I'm using Range
http header in NSURLRequest
, here is more information:
Continue an interrupted download on iPhone
How to implement resumable file downloads on iPhone SDK
So, the problem is not really with AFNetworking (NSURLConnection has same behavior), but, I think, developers of the framework could take into account this situation.
Related videos on Youtube
Alexander
Updated on July 07, 2022Comments
-
Alexander almost 2 years
I'm trying to implement downloading of a large file and show to user current progress, but block in:
-[AFURLConnectionOperation setDownloadProgressBlock:]
returns incorrect
bytesRead
andtotalBytesRead
values (they are smaller than they should be).For example: If I have a 90MB file and when it downloads completely, latest block invocation in
setDownloadProgressBlock:
gives metotalBytesRead
value about 30MB. On other side, if file is 2MB large, latest block invocation gives correcttotalBytesRead
2MB value.AFNetworking is updated to the latest version from github.
If AFNetworking can't do it correctly, what solution can I use?Edit: I've determined that even if file is not downloaded completely (and this happens every time with relatively big file) AFNetworking calls success block in:
-[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]
I asked a similar question here about this situation, but didn't get any answers.
I can check in code downloaded and real file sizes, butAFNetworking
has no API for continuation of partial download. -
Alexander over 11 yearsYes, I understand, my code is identical to yours. I'm only saying that bytesRead also gives incorrect number on large files.
-
Felix over 11 yearscan you give an example? as I said you can ignore
bytesRead
because it is not relevant for progress. -
Felix over 11 yearswhat do you get with
NSLog(@"%u %llu %llu", bytesRead, totalBytesRead, totalBytesExpectedToRead);
? bytesRead should be more or less the same value in each callback. -
Alexander over 11 yearsI've added an example to my question to clarify it. If I sum on every block invocation
bytesRead
it will give value equal tototalBytesRead
, incorrect value in other words. -
Felix over 11 yearsAFNetworking does it correctly, look at the source: github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/… Obviously the connection is cancelled too early, maybe because there is not enough disk space. I assume you have setup a NSOutputStream that writes to file. Otherwise you would consume very much memory and iOS may cancel the download because of that.
-
Felix over 11 yearsFrom the AFNetworking wiki: How do I download a file? Use the outputStream property of AFURLConnectionOperation or its subclasses, setting it to an NSOutputStream that streams to a file at a specified path:
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:@"download.zip" append:NO];
This is especially useful when you're downloading anything relatively large (more than a few MB), since the contents of the file will be streamed directly to the file, rather than being stored in memory. -
Alexander over 11 yearsI've used
outputStream
, but in some sense you are right, file is not downloaded completely to disk. I've updated my question, there are some explanations. -
Erika Electra about 8 years~goodfella "I can compare the number of bytes downloaded with the number of bytes expected to download. (it is not very hard to implement in code). " Could you please elaborate in code? How do you get number of bytes expected? I am having trouble finding such an API from AFNetworking
-
Alexander about 8 yearsYou can find example code in the following class: github.com/onivem/Download, particularly in setCompletionBlocks method. Note that this class has been written for AFNetworking as it was on may 2013.