Downloading large files with AFNetworking

10,636

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.

Share:
10,636

Related videos on Youtube

Alexander
Author by

Alexander

Updated on July 07, 2022

Comments

  • Alexander
    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 and totalBytesRead 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 me totalBytesRead value about 30MB. On other side, if file is 2MB large, latest block invocation gives correct totalBytesRead 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, but AFNetworking has no API for continuation of partial download.

  • Alexander
    Alexander over 11 years
    Yes, I understand, my code is identical to yours. I'm only saying that bytesRead also gives incorrect number on large files.
  • Felix
    Felix over 11 years
    can you give an example? as I said you can ignore bytesRead because it is not relevant for progress.
  • Felix
    Felix over 11 years
    what do you get with NSLog(@"%u %llu %llu", bytesRead, totalBytesRead, totalBytesExpectedToRead);? bytesRead should be more or less the same value in each callback.
  • Alexander
    Alexander over 11 years
    I've added an example to my question to clarify it. If I sum on every block invocation bytesRead it will give value equal to totalBytesRead, incorrect value in other words.
  • Felix
    Felix over 11 years
    AFNetworking does it correctly, look at the source: github.com/AFNetworking/AFNetworking/blob/master/AFNetworkin‌​g/… 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
    Felix over 11 years
    From 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
    Alexander over 11 years
    I'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
    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
    Alexander about 8 years
    You 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.