August 25, 2020

How to save a file from a URL with Swift

How to save a file from a URL with Swift

In this tutorial I will show you how you can download a file from a given URL and then save it locally using Swift.

Setting up the local file URL

The first thing that I want to do is to setup the local file url. In this tutorial I will show you how you can download an image and how you can save that image locally. This will work with any file type, but for now we need to setup the file path.

Below is the code to get the documentDirectory as well as appending a path component(the file name) to the documentDirectory url:

let documentDirectory = FileManager.default.urls(for: .documentDirectory,
                                                in: .userDomainMask)[0]
let imageName = documentDirectory.appendingPathComponent("myImage.png")

Downloading the File

Now that we have the path to the file that we want to write to, let's download the file. To download the file I will use the following code:

// 1
let urlString = "https://raw.githubusercontent.com/programmingwithswift/HowToSaveFileFromUrl/master/testFile.png"

// 2
if let imageUrl = URL(string: urlString) {
    // 3
    URLSession.shared.downloadTask(with: imageUrl) { (tempFileUrl, response, error) in
        
        // 4
        if let imageTempFileUrl = tempFileUrl {
            do {
                // Write to file
            } catch {
                print("Error")
            }
        }
    }.resume()
}

Alright, what is going on in the above code?

  1. We create a constant called urlString that contains the url to the file that we want to download.
  2. We create new instance of URL using the urlString and we unwrap the URL.
  3. Now that we have a URL, we can start with downloading the file. To do this we will use the .downloadTask that is found on URLSession. The .downloadTask will take two arguments, the first will be the url to the file that we want to download, and the second will be a closure so that we can use to handle the response. The closure takes three arguments, tempFileUrl, response and error. The only one we will work with in this tutorial is tempFileUrl, but in production you should make this safer and handle errors.
  4. Now that we have the tempFileUrl we need to unwrap it because it is an optional.

In the above code I have left a comment, Write to file, will update this part in the next step.

Save the downloaded file

We have everything setup so that we can download the file, the next task that we need to do is to save the file locally. To do this, replace, Write to file from the previous sections code with the following code:

// 1
let imageData = try Data(contentsOf: imageTempFileUrl)

// 2
try imageData.write(to: imageName)
  1. In the previous section we unwrapped the tempFileUrl which allows us to use it here. Data allows us to create a new instance by passing through a URL, in this case we will pass through imageTempFileUrl.
  2. If we are able to create a new instance of Data as mentioned in the above point, we will try to write that data to a new file. We are now able to use imageName that we created in the beginning of the tutorial. Data has a built in method that will allow us to write the data to a specified URL, in our case it will be imageName.

Conclusion

Swift makes downloading and saving files locally very easy, just make sure that when using the above code in production, you do it safely.

If you want to see the full source code, you can find it here. In the source code I have a checkSavedImage which will read the saved image from disk just to ensure that the file did save.