Downloading a big file with URLSession downloadTask crashes at end

39 Views Asked by At

I need to download a big mp4 file (>2gb) and it crashes on an iPhone mini but not on a new iPhone 15.

The whole download works well and the memory is stable but when it finishes the memory spikes until the app crashes. I used to do try FileManager.default.moveItem(at: location, to: destinationURL) since I want to save it in a specific directory but even commenting the line the app runs out of memory. Any idea how to do it?

This and print("File downloaded successfully!") the successful completionHandler get called.

private func downloadFile(from url: URL, name: String, progressHandler: @escaping (Double) -> Void, completionHandler: @escaping (URL?, Error?) -> Void) {
        let task = URLSession.shared.downloadTask(with: url) { location, response, error in
            if let error = error {
                print("Error downloading file:", error)
                completionHandler(nil, error)
                return
            }
            
            guard let location = location else {
                print("Download location not available.")
                completionHandler(nil, nil)
                return
            }
            
            guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
                print("Documents directory not found.")
                return
            }

            let destinationURL = documentsDirectory.appendingPathComponent("\(name).mp4")
            do {
//                try FileManager.default.moveItem(at: location, to: destinationURL)
                print("File downloaded successfully!")
                completionHandler(location, nil)
            } catch {
                print("Error moving downloaded file:", error)
                completionHandler(nil, error)
            }
        }
        
        let downloadProgress = task.progress
        let progressQueue = DispatchQueue(label: "com.example.progressQueue", qos: .utility, attributes: .concurrent)
        
        let progress = Progress(totalUnitCount: 100)
        progress.completedUnitCount = 0
        
        let progressTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
            progressQueue.async {
                progress.completedUnitCount = Int64(downloadProgress.fractionCompleted * 100)
                progressHandler(progress.fractionCompleted)
            }
            
            if progress.isFinished {
                timer.invalidate()
            }
        }
        
        task.resume()
    }
0

There are 0 best solutions below