-2

I’m trying to download a file from a URL, I managed to do that however, the it will download to ~Libray directory. How do I change the directory to the downloads folder? or out of the library directory.

Here is my file downloader…

import Foundation

class FileDownloader {

    static func loadFileSync(url: URL, completion: @escaping (String?, Error?) -> Void)
    {
        let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .allDomainsMask).first!

        let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)

        if FileManager().fileExists(atPath: destinationUrl.path)
        {
            print("File already exists [\(destinationUrl.path)]")
            completion(destinationUrl.path, nil)
        }
        else if let dataFromURL = NSData(contentsOf: url)
        {
            if dataFromURL.write(to: destinationUrl, atomically: true)
            {
                print("file saved [\(destinationUrl.path)]")
                completion(destinationUrl.path, nil)
            }
            else
            {
                print("error saving file")
                let error = NSError(domain:"Error saving file", code:1001, userInfo:nil)
                completion(destinationUrl.path, error)
            }
        }
        else
        {
            let error = NSError(domain:"Error downloading file", code:1002, userInfo:nil)
            completion(destinationUrl.path, error)
        }
    }

    static func loadFileAsync(url: URL, completion: @escaping (String?, Error?) -> Void)
    {
        let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)

        if FileManager().fileExists(atPath: destinationUrl.path)
        {
            print("File already exists [\(destinationUrl.path)]")
            completion(destinationUrl.path, nil)
        }
        else
        {
            let session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil)
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            let task = session.dataTask(with: request, completionHandler:
            {
                data, response, error in
                if error == nil
                {
                    if let response = response as? HTTPURLResponse
                    {
                        if response.statusCode == 200
                        {
                            if let data = data
                            {
                                if let _ = try? data.write(to: destinationUrl, options: Data.WritingOptions.atomic)
                                {
                                    completion(destinationUrl.path, error)
                                }
                                else
                                {
                                    completion(destinationUrl.path, error)
                                }
                            }
                            else
                            {
                                completion(destinationUrl.path, error)
                            }
                        }
                    }
                }
                else
                {
                    completion(destinationUrl.path, error)
                }
            })
            task.resume()
        }
    }
}

I took a look at the code and I think it has to do something with this

 let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .allDomainsMask).first!

        let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)

I have tried chinging the code from documentDirectory to desktopDirectory but that still puts it in the library directory. How do I change it from the library directory to the downloads directory?

  • You have two methods, loadFileSync and loadFileAsync. But you didn’t tell us which one you are calling. – matt May 30 '20 at 12:35
  • Also what is your evidence that it downloads to the Library directory? Prove this claim please. – matt May 30 '20 at 12:36

1 Answers1

1

You are running a sandboxed app. The Appname/Data/... directories are aliases of the real directories.

Also, you should use userDomainMask instead of allDomainsMask to search for the path in user's home directory. The correct directory you are looking for is downloadsDirectory.

let downloadsUrl = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
let destinationUrl = downloadsUrl.appendingPathComponent(url.lastPathComponent)

There is another SO thread about sandboxed directories:
how to get /Users/username/Downloads path in a sandboxed app?

Tritonal
  • 607
  • 4
  • 16
  • It downloaded to this path “/Users/Ashwin/Library/Containers/com.Ashwin.searche/Data/Documents/a7d9dd_0d223196a4154259ab9655280c77fbfd.zip” not the downloads –  May 30 '20 at 12:52
  • Your app is sandboxed, you probably need to turn that off to be able to achieve the things you are trying to do. It can be changed in app entitlements, but be sure you know what you are doing. – Tritonal May 30 '20 at 12:56
  • But my apps is a web browser, I need to use app sandbox to search web pages –  May 30 '20 at 13:54
  • This falls outside the scope of your original question, and maybe you should close this one and ask about accessing files in app sandbox. You can read about sandboxed app file permissions here: https://benscheirman.com/2019/10/troubleshooting-appkit-file-permissions/ – Tritonal May 30 '20 at 15:07