Reputation: 745
I'm writing a CLI tool in Swift 4 for MacOS. If I "cheat" and use a shell function, then the curl command, I get exactly the result I'm after:
func shell(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
shell("/usr/bin/curl", "-OL", "http://mywebserver/myfile.whatever")
How do I do the same thing natively in Swift 4? I tried using the just library: https://github.com/dduan/Just but I can't figure out how to simply get it to download a file from a URL to a specific location on the file system. I've also found various solutions for Swift 3 and 5, and iOS which obviously don't work for me.
Upvotes: 2
Views: 960
Reputation: 285170
Simple example: Due to the asynchronous behavior of URLSession
you have to start the runloop after resuming the data task and stop it in the completion handler.
let runLoop = CFRunLoopGetCurrent()
let url = URL(string: "http://mywebserver/myfile.whatever")!
let dataTask = URLSession.shared.dataTask(with: url) { data, response, error in
let returnValue : Int32
if let error = error {
fputs("\(error.localizedDescription)\n", stderr)
returnValue = EXIT_FAILURE
} else {
let result = String(data:data!, encoding:.utf8)!
fputs("\(result)\n", stdout)
returnValue = EXIT_SUCCESS
}
CFRunLoopStop(runLoop)
exit(returnValue)
}
dataTask.resume()
CFRunLoopRun()
The code returns the data in stdout. You can write the data directly to disk, replace
let result = String(data:data!, encoding:.utf8)!
fputs("\(result)\n", stdout)
with
let fileURL = URL(fileURLWithPath: "/Users/me/path/to/file.ext")
do {
try data!.write(to: fileURL)
} catch {
fputs("\(error.localizedDescription)\n", stderr)
}
Upvotes: 1
Reputation: 2315
You can download using downloadTask
let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent("downloadedFile.jpg")
//Create URL to the source file you want to download
let fileURL = URL(string: "https://en.wikipedia.org/wiki/Saint_Martin#/media/File:Saint_martin_map.PNG")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %@", error?.localizedDescription);
}
}
task.resume()
}
Upvotes: 0