This question already has answers here:
How to download file in swift?
(16 answers)
Closed 6 years ago.
I'm trying to download a file using Swift. This is the downloader class in my code:
class Downloader {
class func load(URL: URL) {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let request = NSMutableURLRequest(url: URL)
request.httpMethod = "GET"
let task = session.dataTask(with: URL)
task.resume()
}
}
I call the function like this:
if let URL = URL(string: "https://web4host.net/5MB.zip") {
Downloader.load(URL: URL)
}
but this error message pops up:
2017-02-16 04:27:37.154780 WiFi Testing[78708:7989639] [] __nw_connection_get_connected_socket_block_invoke 2 Connection has no connected handler
2017-02-16 04:27:37.167092 WiFi Testing[78708:7989639] [] __nw_connection_get_connected_socket_block_invoke 3 Connection has no connected handler
2017-02-16 04:27:37.169050 WiFi Testing[78708:7989627] PAC stream failed with
2017-02-16 04:27:37.170688 WiFi Testing[78708:7989639] [] nw_proxy_resolver_create_parsed_array PAC evaluation error: kCFErrorDomainCFNetwork: 2
Could someone tell me what I'm doing wrong and how I could fix it? Thanks!
The code to receive the data is missing.
Either use delegate methods of URLSession or implement the dataTask method with the completion handler.
Further for a GET request you don't need an URLRequest – never use NSMutableURLRequest in Swift 3 anyway – , just pass the URL and don't use URL as a variable name, it's a struct in Swift 3
class Downloader {
class func load(url: URL) { // better func load(from url: URL)
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let task = session.dataTask(with: url) { (data, response, error) in
// handle the error
// process the data
}
task.resume()
}
}
Related
Hi am trying to send custom header with avplayer request so I had added a custom scheme like
let asset = AVURLAsset(url: URL(string: "mycustomscheme://tungsten.aaplimg.com/VOD")!, options: nil)
because of this request fails and delegate method shouldWaitForLoadingOfRequestedResource is called.
In shouldWaitForLoadingOfRequestedResource am making a custom request and am recieving the data from server but avplayer is still not playing the file. Here is my code :
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
resourceLoader.delegateQueue?.async {
var request: URLRequest? = loadingRequest.request
request?.url = self.url
// Add header
request?.setValue(HeadersForWS.DeviceOS, forHTTPHeaderField: HeadersForWS.DeviceType)
request?.setValue(Utility.getUserId(), forHTTPHeaderField:HeadersForWS.UserId )
if let aRequest = request {
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
session.dataTask(with: aRequest as URLRequest) { (data, response, error) in
guard let data = data else {
try? loadingRequest.finishLoading()
return
}
loadingRequest.dataRequest?.respond(with: data)
loadingRequest.finishLoading()
}.resume()
}
}
return true
}
If I save the data received to a file sample.mp4 and pull the file from app and then try to play then it plays means am receiving the video data properly. What may be the problem here??
Thanks in advance
Currently i'm working on downloading a file from server, and this is working good.
my question is how would i know that url has resume capability or not before actual download started?
bellow is some code snippet,
class Downloader:NSObject,URLSessionDownloadDelegate {
/*
SOME PROPERTIES & DECLARATIONS
*/
override init() {
super.init()
let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: url.absoluteString)
backgroundSessionConfiguration.networkServiceType = .default
self.defaultSession = URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
}
func start(_ block:DownloaderCompletionHandler?) {
guard self.input == nil else { return }
guard self.output == nil else { return }
if let data = self.resumableData {
self.downloadTask = self.defaultSession.downloadTask(withResumeData: data)
}else {
let request = URLRequest(url: self.input!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 0.60)
self.downloadTask = self.defaultSession.downloadTask(with: request)
}
self.downloadTask.resume()
}
func pause() {
self.downloadTask.cancel { (data) in
self.resumableData = data
}
}
}
please , guid me on this situation.
THANKS IN ADVANCE
A download can be resumed only if the following conditions are met:
The resource has not changed since you first requested it
The task is an HTTP or HTTPS GET request
The server provides either the ETag or Last-Modified header (or both) in its response
The server supports byte-range requests
The temporary file hasn’t been deleted by the system in response to disk space pressure
→ Source: https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel
if you send a request with Range in HttpHeaders and receive a 206 status code in response , then you can resume the download. otherwise download can not be resumed.
read more about it here
When trying to create my own session object NSURLSession() and request an url I get an unrecognized selector exception but when I use the shared session NSURLSession.sharedSession() everything works fine. How come?
var url = NSURL(string: "http:/www.google.com")
if url != nil {
//throws unrecognized selector when dataTaskWithURL is called
let session=NSURLSession()
session.dataTaskWithURL(url!)
//works
let sharedSession=NSURLSession.sharedSession()
sharedSession.dataTaskWithURL(url!)
}
You have to init URLSession with a configuration:
URLSession(configuration: .default)
or use shared session
URLSession.shared
In SWIFT 3.0 and up:
URLSession.shared.dataTask(with: url, completionHandler:
{
(data, response, error) in
//Your code
}).resume()
Aside from the shared session NSURLSession must be initialized with one of these two methods
init(configuration configuration: NSURLSessionConfiguration)
init(configuration configuration: NSURLSessionConfiguration,
delegate delegate: NSURLSessionDelegate?,
delegateQueue queue: NSOperationQueue?)
Do the initialization while declaration :-
var session = URLSession(configuration: .default)
I'm using Swift in Xcode 6.2 (beta) but had the same problem on the 6.1 release version. I'm trying to use NSURLSession and believe I have it set up correctly (see code below). The problem is that I have a delegate setup to deal with a redirect happening through the code. I actually need to capture the cookies prior to the final redirection and I'm doing this through the delegate:
func URLSession(_:NSURLSession, task:NSURLSessionTask, willPerformHTTPRedirection:NSHTTPURLResponse, newRequest:NSURLRequest, completionHandler:(NSURLRequest!) -> Void )
This works and I'm able to execute code successfully and capture the cookies I need. The problem is that I need to add task.cancel() at the end of the function or else it never seems to complete and return to the delegator (parent?) function. Because of this I lose the results from the redirect URL (although in my current project it is inconsequential). The strange thing is that this was working for a while and seemingly stopped. I don't believe I entered any code that changed it, but something had to happen. Below is the relevant code.
NSURLSession Function:
func callURL (a: String, b: String) -> Void {
// Define the URL
var url = NSURL(string: "https://mycorrecturl.com");
// Define the request object (via string)
var request = NSMutableURLRequest(URL: url!)
// Use default configuration
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
// Create the NSURLSession object with default configuration, and self as a delegate (so calls delegate method)
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
// Change from default GET to POST (needed to call URL properly)
request.HTTPMethod = "POST"
// Construct my parameters to send in with the URL
var params = ["a":a, "b":b] as Dictionary<String, String>
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// Do some other stuff after delegate has returned...
})
task.resume()
return
}
The delegate code:
func URLSession(_:NSURLSession, task:NSURLSessionTask, willPerformHTTPRedirection:NSHTTPURLResponse, newRequest:NSURLRequest, completionHandler:(NSURLRequest!) -> Void ) {
// Check Cookies
let url = NSURL(string: "https://mycorrecturl.com")
var all = NSHTTPCookie.cookiesWithResponseHeaderFields(willPerformHTTPRedirection.allHeaderFields, forURL: url!)
// Get the correct cookie
for cookie:NSHTTPCookie in all as [NSHTTPCookie] {
if cookie.name as String == "important_cookie" {
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(cookie)
}
}
task.cancel()
}
It used to return to the calling function without calling task.cancel(). Is there anything that looks wrong with the code that would cause it to just hang in the delegate function if task.cancel() isn't called?
Edit: What code would I add to fix this.
If you are not canceling the request, your willPerformHTTPRedirection should call the completionHandler. As the documentation says, this completionHandler parameter is:
A block that your handler should call with either the value of the request parameter, a modified URL request object, or NULL to refuse the redirect and return the body of the redirect response.
I want to send http request on every myapp-starting.
How to do this? I try:
class MainViewController: UITableViewController {
func my_request(){
let url = NSURL(string: "http://www.stackoverflow.com")
let request = NSURLRequest(URL: url)
let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)
println(connection)
}
let lol = my_request()
}
But I have an error: Missing argument for parameter #1 in call
How to fix that?
Thanks!
my_request() returns nothing, if you just want to call the function, use only
my_request()
I would suggest to put this in the ViewDidLoad function (on your Main ViewController of your App)