将文件下载到 Swift 4 (Mac OS) 中的临时位置,就像使用 curl

Download a file to a temp location in Swift 4 (Mac OS) like with curl

我正在 Swift 4 中为 MacOS 编写 CLI 工具。 如果我 "cheat" 并使用 shell 函数,然后使用 curl 命令,我会得到我想要的结果:

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")

如何在 Swift 4 中以本地方式执行相同的操作? 我尝试使用 just 库:https://github.com/dduan/Just 但我无法弄清楚如何简单地将文件从 URL 下载到文件系统上的特定位置。 我还找到了 Swift 3 和 5 以及 iOS 的各种解决方案,但显然对我不起作用。

您可以使用downloadTask

下载
  1. 创建会话配置
  2. 使用此配置创建 URLSession
  3. 应用下载任务
  4. 下载成功后,将数据复制到目的地
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()

  }

简单示例:由于URLSession的异步行为,您必须在恢复数据任务后启动runloop,并在完成处理程序中停止它。

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()

代码returns标准输出中的数据。可以将数据直接写入磁盘,替换

let result = String(data:data!, encoding:.utf8)!
fputs("\(result)\n", stdout)

 let fileURL = URL(fileURLWithPath: "/Users/me/path/to/file.ext")
 do {
    try data!.write(to: fileURL)
 } catch { 
   fputs("\(error.localizedDescription)\n", stderr)
 }