38

In older version of Alamofire. This is how I download file

    let destinationPath = Alamofire.Request.suggestedDownloadDestination( directory: .documentDirectory, domain: .userDomainMask);

    Alamofire.download(.GET, urlString, destination: destinationPath)
        .progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
//                print(totalBytesRead)
        }
        .response { request, response, _, error in

            let downloadedFilePath = destinationPath(URL(string: "")!, response!);

            NSUserDefaultsHelper.saveURL(downloadedFilePath, key: urlString);

            completion(downloadedFilePath, true);
    }

But now in the new version, my code is completely unusable and there is no similar function in the Alamofire library.

Any ideas please?

JayVDiyk
  • 4,277
  • 22
  • 70
  • 135
  • 4
    When I Google `Download File Using Alamofire 4.0 (Swift 3)`, I get a link to Alamofire's official documentation which has an [example](https://github.com/Alamofire/Alamofire#downloading-data-to-a-file) on how to download a file. Is that not useful? – Pekka Oct 07 '16 at 08:38

7 Answers7

58

I used to use this statements:

let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)

Alamofire.download(
    url,
    method: .get,
    parameters: parameters,
    encoding: JSONEncoding.default,
    headers: nil,
    to: destination).downloadProgress(closure: { (progress) in
        //progress closure
    }).response(completionHandler: { (DefaultDownloadResponse) in
        //here you able to access the DefaultDownloadResponse
        //result closure
    })

For more details read more in Alamofire docs about Migration to 4.0:

Lazy Ninja
  • 22,342
  • 9
  • 83
  • 103
pedrouan
  • 12,762
  • 3
  • 58
  • 74
17

Swift 4.0

 let destination: DownloadRequest.DownloadFileDestination = { _, _ in
            var documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            documentsURL.appendPathComponent("file.csv")
            return (documentsURL, [.removePreviousFile])
        }

        Alamofire.download(url, to: destination).responseData { response in
            if let destinationUrl = response.destinationURL {
               print("destinationUrl \(destinationUrl.absoluteURL)")
            }
        }
Mujahid Latif
  • 596
  • 7
  • 18
15

There are several enhancements in Alamofire 4. The first of which is the optionality of the destination closure. Now, by default, the destination closure is nil which means the file is not moved anywhere on the file system and the temporary URL is returned.

This is the default execution:-

Alamofire.download(urlString).responseData { response in
    print("Temporary URL: \(response.temporaryURL)")
}

This is my code to download file with Alamofire 4.0 which return destination Url of file:-

let destination: DownloadRequest.DownloadFileDestination = { _, _ in
        var documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        documentsURL.appendPathComponent("duck.png")
        return (documentsURL, [.removePreviousFile])
    }

    Alamofire.download(url, to: destination).responseData { response in
    if let destinationUrl = response.destinationURL ? {
        completionHandler(destinationUrl)
    }
}
The Doctor
  • 486
  • 1
  • 6
  • 16
Shan Shafiq
  • 1,018
  • 10
  • 10
10

Downloading mp3 file with Alamofire 4.0 Swift 4.x

Since almost all samples seems to be about downloading an image or a JSON file, it took me hours to find the right solution.
I will share it here hoping it would help others to save some time.

func startDownload(audioUrl:String) -> Void {
    let fileUrl = self.getSaveFileUrl(fileName: audioUrl)
    let destination: DownloadRequest.DownloadFileDestination = { _, _ in
        return (fileUrl, [.removePreviousFile, .createIntermediateDirectories])
    }

    Alamofire.download(audioUrl, to:destination)
        .downloadProgress { (progress) in
            self.progressLabel.text = (String)(progress.fractionCompleted)
        }
        .responseData { (data) in
            self.progressLabel.text = "Completed!"
    }
}

func getSaveFileUrl(fileName: String) -> URL {
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let nameUrl = URL(string: fileName)
    let fileURL = documentsURL.appendingPathComponent((nameUrl?.lastPathComponent)!)
    NSLog(fileURL.absoluteString)
    return fileURL;
}
Lazy Ninja
  • 22,342
  • 9
  • 83
  • 103
10

For the latest versions this is how it should look like:

let destination: DownloadRequest.Destination = { _, _ in
        let documentsURL = FileManager.default.urls(for: .picturesDirectory, in: .userDomainMask)[0]
            let fileURL = documentsURL.appendingPathComponent("image.png")

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

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

        if response.error == nil, let imagePath = response.fileURL?.path {
            let image = UIImage(contentsOfFile: imagePath)
        }
    }
Cristian Tovar
  • 251
  • 3
  • 6
5

Swift 3 Alamofire (4.4.0):

.plist add key "App Transport Security Settings->Allow Arbitrary Loads->Yes" if you copy and paste code below:

import Alamofire

    let destination = DownloadRequest.suggestedDownloadDestination()

    Alamofire.download("http://zmp3-mp3-lossless-te-zmp3-bdhcm-1.zadn.vn/151e407bb43f5d61042e/1223048424027738068?key=f-zMo3GZKlhVibnvGMsMuQ&expires=1495726053&filename=See%20You%20Again%20-%20Wiz%20Khalifa%20Charlie%20Puth%20(NhacPro.net).flac", to: destination).downloadProgress(queue: DispatchQueue.global(qos: .utility)) { (progress) in
        print("Progress: \(progress.fractionCompleted)")
    } .validate().responseData { ( response ) in
        print(response.destinationURL!.lastPathComponent)
    }
Giang
  • 3,553
  • 30
  • 28
4

Use this code for download file

     let fileManager = FileManager.default
     let directoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

    Alamofire.request(\(downloadUrl)).downloadProgress(closure : { (progress) in
        print(progress.fractionCompleted)

    }).responseData{ (response) in
        print(response)
        print(response.result.value!)
        print(response.result.description)
           let randomString = NSUUID().uuidString
        if let data = response.result.value {

            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
            let videoURL = documentsURL.appendingPathComponent("\(randomString)")
            do {
                try data.write(to: videoURL)

            } catch {
                print("Something went wrong!")
            }

        }
    }
Pankaj Jangid
  • 812
  • 9
  • 18
  • Hi. I downloaded success but can not find where is my video, can u help? – famfamfam Jan 19 '19 at 16:56
  • @famfamfam you can find the file in document directory – Pankaj Jangid Jan 19 '19 at 18:02
  • Hi. here is my file url : 'file:///Users/thehe/Library/Developer/CoreSimulator/Devices/01F3C177-1B6A-4CB4-AABE-45EB0D57A3C1/data/Containers/Data/Application/DEA4544E-54A9-4104-9A7A-CAF5B9D172B3/Documents/CiviX_HistoryVideo_19-1-2019_7h59m28s.mp4' , then my error i got is 'The file “CiviX_HistoryVideo_19-1-2019_7h59m28s.mp4” couldn’t be saved in the folder “Documents”.' – famfamfam Jan 19 '19 at 18:06
  • @famfamfam please check progress rate, If it is 100% then It will be saved into document directory – Pankaj Jangid Jan 21 '19 at 05:33