Alamofire下载问题

Tul*_*leb 19 swift alamofire

我试图使用带有Xcode 8.0和Swift 3.0的Alamofire 4.0.0在我的代码中下载这张图片.

这是我的要求:

    func download(_ path: String, _ completionHandler: @escaping (Any?) -> ()) {
        let stringURL = "https://slove.tulleb.com/uploads/6/6/0/2/66027561/2791411.jpg-1447979839.png"

        print("Requesting \(stringURL)...")

        _ = Alamofire.download(stringURL)
            .responseData { response in
                print(response)

                if let data = response.result.value {
                    completionHandler(UIImage(data: data))
                } else {
                    completionHandler(nil)
                }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我从服务器得到以下答案:

FAILURE:responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputFileReadFailed(file:///private/var/mobile/Containers/Data/Application/50400F41-47FD-4276-8903-F48D942D064A/tmp/CFNetworkDownload_D1Aqkh.tmp)))

我对如何解决这个问题一无所知...... Alamofire新版本是否存在某些问题,还是我在某处遗忘了某些东西?

谢谢!

Tul*_*leb 30

来自cnoon(Alamofire会员)的官方回答:

嗨@Tulleb,

抱歉不要早点回复你.示例@katopz与请求类型不同.该示例演示了如何使用数据任务,而不是下载任务.如果您不想下载该文件,则可以执行以下操作:

Alamofire.request(url).responseData { response in
     guard let data = response.result.value else { return }
     let image = UIImage(data: data)
     print(image)
}
Run Code Online (Sandbox Code Playgroud)

但是,要回答您的原始问题,您将遇到沙箱权限问题.我们允许您使用下载API,而无需为macOS等操作系统指定目标闭包,您可以在其中访问自己沙箱之外的文件.但是,在iOS上,您无法直接访问沙箱外部的文件数据.这就是你看到.inputFileReadFailed错误的原因.

有几种方法可以解决这个问题.

选项1

您可以使用请求API下载数据,如上所示,它将图像数据下载到内存中,而不是下载到磁盘.

选项2

您可以在使用目标闭包访问数据之前将文件移动到沙箱中.这是一个如何做到这一点的例子:

let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,
.userDomainMask, true)[0]
let documentsURL = URL(fileURLWithPath: documentsPath, isDirectory: true)
let fileURL = documentsURL.appendingPathComponent("image.png")

return (fileURL, [.removePreviousFile, .createIntermediateDirectories]) }

Alamofire.download("https://httpbin.org/image/png", to:
destination).responseData { response in
    debugPrint(response)

    if let data = response.result.value {
        let image = UIImage(data: data)
        print(image)
    } else {
        print("Data was invalid")
    }
}
Run Code Online (Sandbox Code Playgroud)

//输出:

// [请求]:https://httpbin.org/image/png // [回复]:{URL:https://httpbin.org/image/png } {status code:200,headers {//"Access -Control-Allow-Origin"="*"; //"Content-Length"= 8090; //"Content-Type"="image/png"; // Date ="Sat,2016年9月24日21:34:25 GMT"; //
Server = nginx; //"access-control-allow-credentials"= true; //}} // [TemporaryURL]:/private/var/mobile/Containers/Data/Application/25612024-9A05-4ED5-AF3B-A98E22DEAD7A/tmp/CFNetworkDownload_fD9sXf.tmp // [DestinationURL]:/ var/mobile/Containers /Data/Application/25612024-9A05-4ED5-AF3B-A98E22DEAD7A/Documents/image.png // [ResumeData]:0字节// [结果]:成功:8090字节// [时间轴]:时间轴:{"请求开始时间":496445664.792,"初始响应时间":496445665.651,"请求完成时间":496445665.655,"序列化完成时间":496445665.655,"延迟":0.860秒,"请求持续时间":0.863秒,"序列化持续时间":0.000 secs,"总持续时间":0.864秒} //可选(,{100,100})如果需要将文件下载到磁盘,必须使用目标闭包.临时文件只能在委托回调中访问,该回调在Alamofire内部处理.如果您未在iOS上指定目标闭包,则temporaryURL将始终指向临时文件先前存储的位置,但已清除.

摘要

总而言之,如果您不需要将数据下载到磁盘,那么您需要选项1.如果您确实要将文件保存在磁盘上,那么您需要选项2.

干杯.