2014-10-10 3 views
21

Пример использования Alamofire.download() работает очень хорошо, но нет никаких подробностей о том, как получить доступ к результирующему загруженному файлу. Я могу выяснить, где находится файл и что он был назван, на основе установленного адресата и исходного запроса на файл, который я сделал, но я бы предположил, что есть значение, которое я должен иметь доступ, чтобы получить полный конечный путь загрузки и имя файла в ответе.Метод Alamofire.download(): Где находится файл и он успешно сохранил?

Как получить доступ к имени файла и как узнать, успешно ли он был сохранен? Я вижу методы делегата в фактическом коде Alamofire, который, как представляется, обрабатывает вызовы завершения делегирования для процесса загрузки, но как я могу/я могу получить доступ к данным файла в блоке .response?

+0

я собирался задать тот же вопрос, у меня такая же проблема прямо сейчас! – dburgmann

ответ

13

Пример в файле readme 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!) 
     } 
} 
+1

вы не можете получить доступ к переменной finalPath или fileName оттуда – Gabox

+1

Если вы хотите получить доступ к finalPath или fileName в закрытии, вам необходимо изменить вызов загрузки на «Alamofire.download (.GET, urlToCall, {[weak self] (timeURL, response) в « Затем вы можете ссылаться на self.fileName и self.finalPath, не вызывая цикл сохранения. Кроме того, вам нужно поместить этот код в класс, созданный в том месте, где он не выйдет из сферы действия до завершения запроса Более простой подход заключается в том, чтобы добавить закрытие обработки завершения к функции, где этот код, и передать finalPath этому обработчику завершения. –

3

Я провел около 8 часов в поисках ответа на этот один. Решение ниже работает для меня, и в основном я подключаюсь к методу загрузки для отображения изображения. В приведенном ниже примере я загрузив изображение профиля пользователя, зная его ID Facebook:

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!) 
       } 
      } 
    } 
25

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

Тем не менее трудно понять, почему они используют затворы установить путь назначения ...

+2

Если файл назначения уже существует, переименование/перемещение не удастся, поэтому обработка этот случай в закрытии удобен, если вы хотите использовать предложенное имя файла. – penfold

+0

@penfold true, это сэкономит мне много усилий, написав логику, чтобы заменить существующий файл новым файлом и восстановить из временного файла, если загрузка не удалась. Я действительно рад, что это закрытие. – spaceMonkey

2

Вот полный метод для загрузки файла в другой пункт назначения с прогрессом

// МАРК: методы скачать

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

} 
2

This answer от члена Alamofire, кажется, лучший ответ:

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