Tip

AFNetworking: Downloading Files with Progress

I was looking for this the other day, and while there are a ton of solutions out there, I felt that all of them were just a tad more complicated than they needed to be to achieve the desired result. Basically, I’m working on an app that needs to download videos and show what percentage of the files have been downloaded in a UITableView. Standard stuff, but for some reason it’s not already built in to AFNetworking. After tinkering around with a few different solutions online, I ended up coming up with my own (shown below). I ended up creating a class called MFVideoDownloader and adding the the following class method to the .m:

While the snippet contains more detailed comments, I’ll just go through what I did really quickly.

    1. First I created the session manager to handle the actual download task that comes about later in the method.
    2. Then I converted the given NSString into an NSURL so it can be used later (I’m working with a REST API that gives me back the URLs I need as strings so it made more sense to convert it here rather than have to convert every place I call the method in app).
    3. After this, I hook in to the manager and watch the number of bytes received so I can display them to the user (in my case as an overlay on a UITableViewCell).
    4. The next step is to make the download task and check if there’s already a video at the file path I’m saving to. If there is one, I delete it and replace it with the latest one using the helper method at the bottom of the snippet.
    5. Finally, I kick off the download task.

Overall, the process is pretty simple. I’m planning to expand on this class a lot for a project I’m working on, but this was the quick and dirty approach I took to get a v1.0 into the app store. Also just a quick note that when updating the progress to display to the user, be sure that you do so on the main thread. Right now the call happens on a background thread so unless you explicitly update your UI on the main tread it won’t display any changes.

8 thoughts on “AFNetworking: Downloading Files with Progress”

  1. Vatsal Shukla says:

    hi sir,
    i read your blog and it helped me a lot. thank you.
    while reading this blog. i thought that how to get downloading file information before starting downloading task. please guide me.

    1. tarikfayad says:

      Hey! If you’re just trying to get the file size it’s actually already in the code snippet above. “totalBytesExpectedToWrite” should give you the overall file size of whatever you’re downloading.

      1. Lawrence says:

        Hello,
        I appreciate you writing this. What if you were downloading multiple files? The totalBytesExpectedToWrite only displays info for the current files. The same with totalBytesWritten. How would you go about displaying overall progress?

        1. Tarik Fayad says:

          Hey! This is off the top of my head, but there are a couple of ways I can think of to do this:

          1) If they’re all the same sort of file, you could steal a page out of Apple’s book and sort of spoof the progress bar (the progress bar in iMessage is just a timed animation). For instance, let’s say you’re uploading 5 images, you could get the totalBytesExpectedToWrite in the snippet above, then multiply it by 5 to get an estimate of the overall size (not an ideal way, but could be workable).

          2) The other way that came to mind would be to make all your NSURLSessionDownloadTasks up front, and then add up all of their countOfBytesExpectedToSend. I haven’t had a chance to set this, but it seems like it should work. I’ll do my best to make some time and play around with it tonight, but let me know if you discover anything!

          1. Lawrence says:

            Thanks so much for your reply! Your points gave me an idea. I was able to get the total download size using some test code that downloaded all the files. I kept track with a global variable. Now I can get percentage by dividing the totalbyteswritten by my download size. I also moved my progress view update to didFinishDownloadingToURL. I still would like to be able to do this without knowing the size so I may try your second point as well. Thanks for getting my brain going!

          2. Tarik Fayad says:

            Awesome! Glad I could help!!

        2. Nazir says:

          I think that better when you do not know the total size of all files and when every file (image) could be in a different size, the best way is:
          1. Divide the progress bar with number of files you will download (that will be steps)
          2. Divide each step on to size of current file
          This will give you real progress bar without extra work.

  2. Abhilash P says:

    This one saved my day. Really an awesome and simple to use module. Thanks Tarik Fayad.

Leave a Reply

Your email address will not be published. Required fields are marked *