首次使用或应用程序进入后台时下载失败

Posted

技术标签:

【中文标题】首次使用或应用程序进入后台时下载失败【英文标题】:Download fails when on first use or app goes in background 【发布时间】:2016-11-04 12:34:31 【问题描述】:

Alamofire 3.5.0、Swift2.2

我正在使用 Alamofire 下载方法下载 ZIP 文件,我注意到当我开始下载过程并且应用程序进入后台时,下载失败并出现以下错误:

----------------------
error Optional(Error Domain=NSCocoaErrorDomain Code=4
    "“CFNetworkDownload_pZ56nc.tmp” couldn’t be moved to “courses”
    because either the former doesn't exist, or the folder containing
    the latter doesn't exist." UserInfo=
    NSSourceFilePathErrorKey=
/private/var/mobile/Containers/Data/Application/[UUID]/tmp/CFNetworkDownload_pZ56nc.tmp, 
    NSUserStringVariant=(
        Move
    ),     
    NSDestinationFilePath=
/var/mobile/Containers/Data/Application/[UUID]/Library/courses/course_302.zip, 
    NSFilePath=
/private/var/mobile/Containers/Data/Application/[UUID]/tmp/CFNetworkDownload_pZ56nc.tmp, 
    NSUnderlyingError=0x13f52f990 Error Domain=NSPOSIXErrorDomain
    Code=2 "No such file or directory")
----------------------

这是下载文件的代码:

//...
var userLibraryPath:String = 
    return NSSearchPathForDirectoriesInDomains(.LibraryDirectory, .UserDomainMask, true)[0]
()

//...
let _coursePath:NSURL = NSURL(string: "file://\(userLibraryPath)/)")!
//...
let zipURL = _coursePath.URLByAppendingPathComponent("course_\(courseId).zip")
        //if file exists destroy it
        if let zipPath = zipURL?.path where NSFileManager.defaultManager().fileExistsAtPath(zipPath) 
            do 
                try NSFileManager.defaultManager().removeItemAtPath(zipPath)
             catch let error as NSError 
                print(error)
            
        
        //
        let downloadRequest = Alamofire.download(Router.download(courseId), destination:  (url:NSURL, urlResponse:NSHTTPURLResponse) -> NSURL in
            //
            return zipURL!
            //
        ).progress( (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
            //
            let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)

            dispatch_async(GlobalMainQueue, 
                self.notifyDownloadProgress(courseId, progress: progress)
            )

        ).response(completionHandler:  (request:NSURLRequest?, response:NSHTTPURLResponse?, data:NSData?, error:NSError?) in
            self.removeFromQueue(courseId)
            print("response")
            print("----------------------")
            print("error \(error)")
            print("----------------------")
            //here I would try to extract it
)

更新我刚刚在 iPhone 5 全新安装的应用程序上进行了测试,它不必进入后台(例如通过主页按钮)失败,它在第一次加载时失败(以及任何后续)直到应用被杀死并重新打开。

为什么要在路径中添加“/private”位?我在这里做错了什么?

【问题讨论】:

【参考方案1】:

确实是“没有这样的文件或目录”错误。

当我添加时:

//
let downloadRequest = Alamofire.download(Router.download(courseId), destination:  (url:NSURL, urlResponse:NSHTTPURLResponse) -> NSURL in
    let course = zipURL!.URLByDeletingLastPathComponent!.path!
    let fm = NSFileManager.defaultManager()
    var isDir:ObjCBool = false
    if(fm.fileExistsAtPath(path, isDirectory: &isDir) == false)
       //doesnt exist
       do 
           try fm.createDirectoryAtPath(path, withIntermediateDirectories: true, attributes: nil)
        catch let error as NSError 
           //
           print(error)
       
    

    return zipURL!
    //
 )

【讨论】:

以上是关于首次使用或应用程序进入后台时下载失败的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 上,当应用程序进入后台时 UnityWebRequest 下载停止

Swift URLSession DataTask 在应用程序进入后台时失败

微信小程序 onLoad 函数

微信小程序 onLoad 函数

停止设备进入睡眠模式一段时间

应用程序进入后台后未调用 AFNetworking 成功/失败块