Download file from server using Swift

20,338

edit/update: Xcode 11.5 • Swift 5.2

import UIKit
import AVFoundation

class ViewController: UIViewController {
    var player: AVPlayer!
    override func viewDidLoad() {
        super.viewDidLoad()
        let alarm = URL(string: "https://www.ringtonemobi.com/storage/upload/user_id_1/iphone-5-alarm-2016-08-21-01-49-25.mp3")!
        do {
            try alarm.download(to: .documentDirectory) { url, error in
                guard let url = url else { return }
                self.player = AVPlayer(url: url)
                self.player.play()
            }
        } catch {
            print(error)
        }
    }
}

import Foundation
extension URL {
    func download(to directory: FileManager.SearchPathDirectory, using fileName: String? = nil, overwrite: Bool = false, completion: @escaping (URL?, Error?) -> Void) throws {
        let directory = try FileManager.default.url(for: directory, in: .userDomainMask, appropriateFor: nil, create: true)
        let destination: URL
        if let fileName = fileName {
            destination = directory
                .appendingPathComponent(fileName)
                .appendingPathExtension(self.pathExtension)
        } else {
            destination = directory
            .appendingPathComponent(lastPathComponent)
        }
        if !overwrite, FileManager.default.fileExists(atPath: destination.path) {
            completion(destination, nil)
            return
        }
        URLSession.shared.downloadTask(with: self) { location, _, error in
            guard let location = location else {
                completion(nil, error)
                return
            }
            do {
                if overwrite, FileManager.default.fileExists(atPath: destination.path) {
                    try FileManager.default.removeItem(at: destination)
                }
                try FileManager.default.moveItem(at: location, to: destination)
                completion(destination, nil)
            } catch {
                print(error)
            }
        }.resume()
    }
}


Original answer

Xcode 8.3.2 • Swift 3.1

if let audioUrl = URL(string: "http://freetone.org/ring/stan/iPhone_5-Alarm.mp3") {
    // create your document folder url
    let documentsUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    // your destination file url
    let destination = documentsUrl.appendingPathComponent(audioUrl.lastPathComponent)
    print(destination)
    // check if it exists before downloading it
    if FileManager.default.fileExists(atPath: destination.path) {
        print("The file already exists at path")
    } else {
        //  if the file doesn't exist
        //  just download the data from your url
        URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) in
            // after downloading your data you need to save it to your destination url
            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix("audio"),
                let location = location, error == nil
                else { return }
            do {
                try FileManager.default.moveItem(at: location, to: destination)
                print("file saved")
            } catch {
                print(error)
            }
        }).resume()
    }
}
Share:
20,338
Admin
Author by

Admin

Updated on July 14, 2022

Comments

  • Admin
    Admin almost 2 years

    Hi I have a whole bunch of .mp3 files I want to use with NSFileManager and store in the documents folder. Is there a way I can download the .mp3 files online and then have it save to the documents folder? This is what I'm using for a local file.

    let filemanager = NSFileManager.defaultManager()
    let documentsPath : AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0]
    let destinationPath:NSString = documentsPath.stringByAppendingString("/Attention.mp3")
    
    if (!filemanager.fileExistsAtPath(destinationPath)) {
      var theError: NSError?
      let fileForCopy = NSBundle.mainBundle().pathForResource("Attention",ofType:"mp3")
      filemanager.copyItemAtPath(fileForCopy!,toPath:destinationPath, error: &theError)
    
      if (theError == nil) {
        println("The music files has been saved.")
      } else {
        println("Error")
      }
    } else {
      println("The files already exist")
    }
    
  • Admin
    Admin over 9 years
    That's if I want to use a local file. I already know how to do that. I'm wondering how I can download a .mp3 via a link and save it to the downloads folder.
  • Admin
    Admin over 9 years
    You're awesome dude! Exactly what I was looking for. Just a quick question, what if I had multiple links? Can I just throw them into an array some how?
  • Admin
    Admin over 9 years
    No problem! You've been a huge help. Thank you!
  • Admin
    Admin over 9 years