Almofire multiple images Download and save them locally

210 views Asked by At

I have more than 500 image links I want to download those images and store locally in app document directory when app starts. I am using Almofire for download but I am getting error like "URLSession task was cancelled" and Request timeOut

func downloadAllImages(images:[String: String], retryCount: Int = 0,completion: @escaping((Bool)->Void)){
        var success: Bool = true
        var failedImages = [String: String]()
        for (localName, severPath) in images {
            self.dispatchGroup.enter()
            
            let destination: DownloadRequest.Destination = { _, _ in
                let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
                let fileURL = documentsURL.appendingPathComponent(localName)
                return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
            }
           
            
            let path = severPath.replacingOccurrences(of: "\\", with: "/").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
        
            //AF.sessionConfiguration.httpShouldSetCookies = false
            AF.download(path, to: destination).response { response in
                switch response.result {
                case .success(_):
                    break
                case .failure(let error):
                    if response.response?.statusCode != 404 {
                        success = false
                        failedImages[localName] = path
                        print("Image Download Error = \(error.localizedDescription)")
                    }
                    break
                }
                debugPrint(response)
                self.dispatchGroup.leave()
            }
        }
        dispatchGroup.notify(queue: .main) {
            //retry If some Images failed to download
            if failedImages.isEmpty || retryCount >= self.maximumRetryCount {
                completion(success)
            }else {
                self.downloadAllImages(images: failedImages, retryCount: retryCount + 1) { (success) in
                    completion(success)
                }
            }
        }
    }

images dictionary contains localName as key serverPath as value

1

There are 1 answers

0
Vitalii Shvetsov On

AFImageDownloaders have limit of active downloads, and I believe changing maximumActiveDownloads or something similar in your API will fix that. The new downloads just cancel the previous ones. But it's better to download them in chunks.

For example this one is for ImageDownloader

 public init(session: Session,
                downloadPrioritization: DownloadPrioritization = .fifo,
                maximumActiveDownloads: Int = 4,
                imageCache: ImageRequestCache? = AutoPurgingImageCache()) {
        precondition(!session.startRequestsImmediately, "Session must set `startRequestsImmediately` to `false`.")

        self.session = session
        self.downloadPrioritization = downloadPrioritization
        self.maximumActiveDownloads = maximumActiveDownloads
        self.imageCache = imageCache
    }

UPD: The limit is not on AF, but URLSession's. And one AF downloader uses one URLSession. You have to pass custom URLSessionConfigurations to handle more active downloads HTTPMaximumConnectionsPerHost. And pass it AF Session class