Post

Replies

Boosts

Views

Activity

Reply to UrlSession.shared.data returns "The network connection was lost."
Thank you @eskimo for your researches. I will study very carefully the link you provided in your answer. I didn't know that NSUrlSession sends a default user string, specific to your application, like in https://stackoverflow.com/questions/36379347/does-nsurlsession-send-user-agent-automatically and https://www.whatismybrowser.com/guides/the-latest-user-agent/safari. Meanwhile I've added this to my code: config.httpAdditionalHeaders = ["User-Agent": ""] and in fact my app works! So the reason why in .NET this code was working, is that there no user-agent is added automatically. Only, I can't find any reference in the official Apple docs that a default user agent is sent with the requests. Maybe they could add docs about it, and how to disable or customize it. (https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411532-httpadditionalheaders says that you could eventually ADD your custom agent). Netherdeless, thank you very much for your support. I will learn a lot studying your answer. Please take this as a very hearted appreciation email for your manager!
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
P.S: in case someone wants to help me, here is the ViewModel that I use now for the download (clearly it's just POC code): // // DownloadForegroundViewModel.swift // MacDownloader // // Created by Damiano Curia on 27.05.23. // import Foundation @MainActor class DownloadForegroundViewModel: NSObject, ObservableObject { //let fileToDownload = "https://example.com/" //let fileToDownload = "https://speed.hetzner.de/100MB.bin" //let fileToDownload = "https://nbg1-speed.hetzner.com/100MB.bin" let fileToDownload = "https://www.backade.com/22Z9H358/SZCPXRW/?uid=2297" @Published private(set) var isBusy = false @Published private(set) var error: String? = nil @Published private(set) var percentage: Int? = nil @Published private(set) var fileName: String? = nil @Published private(set) var downloadedSize: UInt64? = nil // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites private lazy var urlSession: URLSession = { let config = URLSessionConfiguration.default config.waitsForConnectivity = true config.allowsCellularAccess = true config.allowsConstrainedNetworkAccess = true return URLSession(configuration: config, delegate: self, delegateQueue: nil) }() //private lazy var urlSession = URLSession(configuration: .default, // delegate: self, // delegateQueue: nil) @Published private var downloadTask: URLSessionDownloadTask? = nil func downloadToFileWithProgress() async { self.isBusy = true self.error = nil self.percentage = 0 self.fileName = nil self.downloadedSize = nil let downloadTask = urlSession.downloadTask(with: URL(string: fileToDownload)!) downloadTask.resume() self.downloadTask = downloadTask } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads @Published private var resumeData: Data? = nil var canPauseDownload: Bool { get { return self.downloadTask != nil && self.resumeData == nil } } func pauseDownload() { guard let downloadTask = self.downloadTask else { return } downloadTask.cancel { resumeDataOrNil in guard let resumeData = resumeDataOrNil else { // download can't be resumed; remove from UI if necessary return } Task { @MainActor in self.resumeData = resumeData } } } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads var canResumeDownload: Bool { get { return self.resumeData != nil} } func resumeDownload() { guard let resumeData = self.resumeData else { return } let downloadTask = urlSession.downloadTask(withResumeData: resumeData) downloadTask.resume() self.error = nil self.downloadTask = downloadTask self.resumeData = nil } } extension DownloadForegroundViewModel: URLSessionDownloadDelegate { // https://stackoverflow.com/questions/59483557/disable-https-get-certificate-check-in-swift-5 public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { //Trust the certificate even if not valid let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!) completionHandler(.useCredential, urlCredential) } // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { if downloadTask != self.downloadTask { return } let percentage = Int(totalBytesWritten * 100 / totalBytesExpectedToWrite) Task { @MainActor in self.percentage = percentage } } // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { if downloadTask != self.downloadTask { return } defer { Task { @MainActor in self.isBusy = false } } guard let httpResponse = downloadTask.response as? HTTPURLResponse else { Task { @MainActor in self.error = "No HTTP Result" } return } guard (200...299).contains(httpResponse.statusCode) else { Task { @MainActor in self.error = "Http Result: \(httpResponse.statusCode)" } return } let fileName = location.path let attributes = try? FileManager.default.attributesOfItem(atPath: fileName) let fileSize = attributes?[.size] as? UInt64 Task { @MainActor in self.error = nil self.percentage = 100 self.fileName = fileName self.downloadedSize = fileSize self.downloadTask = nil } } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { guard let error = error else { return } Task { @MainActor in self.error = error.localizedDescription } let userInfo = (error as NSError).userInfo if let resumeData = userInfo[NSURLSessionDownloadTaskResumeData] as? Data { Task { @MainActor in self.resumeData = resumeData } } else { Task { @MainActor in self.isBusy = false self.downloadTask = nil } } } } And this is the minimal UI (that sets the button text to "100" when download is complete, otherwise error is shown in Xcode): import SwiftUI struct ContentView: View { @ObservedObject var vm: DownloadForegroundViewModel var body: some View { Button(String(vm.percentage ?? 0)) { Task { await vm.downloadToFileWithProgress() } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView(vm: DownloadForegroundViewModel()) } }
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
Hi, I still have this issue and I have done the following tests: on a Mac app, it has the same identical issue (so I am testing on the Mac app now) I have developed a MAUI app (.NET) and deployed to the iPhone. It works fine and can download the file If I use other urls, my code works fine I have tried disabling NSAppTransportSecurity allowing NSAllowsArbitraryLoads. I can download http content, but this content is still wrong I have tested on this url, that sends a redirect, and it also works fine: https://www.backade.com/22Z9H358/SZCPXRW/?uid=2297 So the issue is just between the Swift libraries and this website. Other websites (even in Swift) or other languages (.NET on both Windows and iOS) work fine Clearly both Chrome and Safari can download this file. Can anyone give me additional tips trying to fix this issue? Regards, Damiano
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
A couple of updates: the download works from Chrome and .NET (created a sample app) old installation of the app, deployed to old iPhones, manifest now the same issue tried to run the app from MacOS - same error I have found this thread https://developer.apple.com/forums/thread/84608 where the server was blocking downloads from unknows networks - but still it works with WiFi. To me, it doesn't work in both 5G and wifi, and even from computers - but the .NET code works fine. So I would still appeciate some help from the community.
Apr ’23