【问题标题】:Alamofire.download() method: Where is the file and did it save successfully?Alamofire.download() 方法:文件在哪里,是否成功保存?
【发布时间】:2014-12-06 01:56:15
【问题描述】:

使用 Alamofire.download() 的示例运行良好,但没有任何关于如何访问生成的下载文件的详细信息。我可以根据我设置的目标和我提出的原始文件请求找出文件的位置和名称,但我会假设我应该能够访问一个值以获得完整的最终下载路径和响应中的文件名。

我如何访问文件的名称以及如何知道它是否保存成功?我可以在实际的 Alamofire 代码中看到似乎处理下载过程的委托完成调用的委托方法,但是我/我如何访问 .response 块中的文件详细信息?

【问题讨论】:

  • 我正要问同样的问题,因为我现在有同样的问题!

标签: alamofire


【解决方案1】:

Swift 2.1 和更简单一点:

var localPath: NSURL?
Alamofire.download(.GET,
    "http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v",
    destination: { (temporaryURL, response) in
    let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
    let pathComponent = response.suggestedFilename
            
    localPath = directoryURL.URLByAppendingPathComponent(pathComponent!)
        return localPath!
    })
    .response { (request, response, _, error) in
        print(response)
        print("Downloaded file to \(localPath!)")
    }
)

仍然很难理解他们为什么要使用闭包来设置目标路径...

【讨论】:

  • 如果目标文件已经存在,重命名/移动将失败,所以如果你想使用建议的文件名,在闭包中处理这种情况很方便。
  • @penfold true 这通过编写用新文件替换现有文件并在下载失败时从临时文件恢复的逻辑为我节省了很多精力。我真的很高兴它的关闭。
【解决方案2】:

Alamofire 自述文件中的示例实际上包含文件路径,因此我使用单独的变量来获取它,以便在代码的其他地方使用。它不是很优雅,我希望有一种方法可以在响应中获取该信息,但现在,这是完成工作:

var fileName: String?
var finalPath: NSURL?

Alamofire.download(.GET, urlToCall, { (temporaryURL, response) in

    if let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {    

        fileName = response.suggestedFilename!
        finalPath = directoryURL.URLByAppendingPathComponent(fileName!)
        return finalPath!
    }

    return temporaryURL
})
    .response { (request, response, data, error) in

        if error != nil {
            println("REQUEST: \(request)")
            println("RESPONSE: \(response)")
        } 

        if finalPath != nil {
            doSomethingWithTheFile(finalPath!, fileName: fileName!)
        }
 }

【讨论】:

  • 你无法从那里访问 finalPath 或 fileName 变量
  • 如果要访问闭包中的finalPath或fileName,需要将下载调用改为“Alamofire.download(.GET, urlToCall, { [weak self] (temporaryURL, response) in”然后您可以引用 self.fileName 和 self.finalPath 而不会导致保留循环。此外,您需要将此代码放在一个实例化的类中,该类在请求完成之前不会超出范围。一种更简单的方法就是给这个代码所在的函数添加一个完成处理闭包,并将finalPath传递给那个完成处理程序。
【解决方案3】:

我花了大约 8 个小时来寻找这个问题的答案。下面的解决方案对我有用,基本上我链接到下载方法来显示图像。在下面的示例中,我正在下载知道其 Facebook ID 的用户的个人资料图片:

    let imageURL = "http://graph.facebook.com/\(FBId!)/picture?type=large"

    let destination: (NSURL, NSHTTPURLResponse) -> (NSURL) = {
        (temporaryURL, response) in

        if let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {
            var localImageURL = directoryURL.URLByAppendingPathComponent("\(self.FBId!).\(response.suggestedFilename!)")
            return localImageURL
        }
        return temporaryURL
    }

    Alamofire.download(.GET, imageURL, destination).response(){
        (_, _, data, _) in
            if let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {
                var error: NSError?
                let urls = NSFileManager.defaultManager().contentsOfDirectoryAtURL(directoryURL, includingPropertiesForKeys: nil, options: nil, error: &error)

                if error == nil {
                    let downloadedPhotoURLs = urls as! [NSURL]
                    let imagePath = downloadedPhotoURLs[0] // assuming it's the first file
                    let data = NSData(contentsOfURL: imagePath)
                    self.viewProfileImage?.image = UIImage(data: data!)
                }
            }
    }

【讨论】:

    【解决方案4】:

    这是在不同目的地下载文件的完整方法

    //MARK:下载方法

    func downloadFile(reqType : RequestType,  urlParam: String,completionHandler: (Double?, NSError?) -> Void) {
    
        let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
        var downloadPath = documentsPath.URLByAppendingPathComponent("downloads")
        var isDirectory: ObjCBool = false
        if NSFileManager.defaultManager().fileExistsAtPath(downloadPath.path!, isDirectory: &isDirectory) {
            if(!isDirectory){
                do {
                    try NSFileManager.defaultManager().createDirectoryAtPath(downloadPath.path!, withIntermediateDirectories: true, attributes: nil)
                }catch  {
                    NSLog("Unable to create directory ")
                }
            }
        }else{
            do {
                try NSFileManager.defaultManager().createDirectoryAtPath(downloadPath.path!, withIntermediateDirectories: true, attributes: nil)
            }catch  {
                NSLog("Unable to create directory ")
            }
    
        }
    
    
        //get the url from GTM
        let urlString = self.getRequestedUrlFromIdentifier(reqType, param: urlParam)
        let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
        Alamofire.download(.GET, urlString, destination: { (temporaryURL, response) in
    
            let pathComponent = response.suggestedFilename
            downloadPath = downloadPath.URLByAppendingPathComponent(pathComponent!)
            if NSFileManager.defaultManager().fileExistsAtPath(downloadPath.path!) {
                do{
                 try NSFileManager.defaultManager().removeItemAtPath(downloadPath.path!)
                }catch {
    
                }
            }
            return downloadPath
        })            .progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
                print(totalBytesRead)
    
                // This closure is NOT called on the main queue for performance
                // reasons. To update your ui, dispatch to the main queue.
                dispatch_async(dispatch_get_main_queue()) {
                    print("Total bytes read on main queue: \(totalBytesRead)")
                }
            }
            .response { request, response, _, error in
                print(response)
                let originalPath = destination(NSURL(string: "")!, response!)
                if let error = error {
                    completionHandler(500000.1 , nil)
                    print("Failed with error: \(error)")
                } else {
                    completionHandler(500000.0 , nil)
                    print("Downloaded file successfully \(downloadPath)")
                }
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      来自 Alamofire 成员的This answer 似乎是最佳答案:

      let destination = Alamofire.Request.suggestedDownloadDestination(
          directory: .CachesDirectory,
          domain: .UserDomainMask
      )
      
      Alamofire.download(.GET, "http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf", destination: destination)
          .progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
              print(totalBytesRead)
          }
          .response { request, response, _, error in
              print(response)
              print("fileURL: \(destination(NSURL(string: "")!, response))")
      }
      

      【讨论】:

        猜你喜欢
        • 2014-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多