Alamofire: Get downloaded file path

Created on 4 Nov 2015  路  10Comments  路  Source: Alamofire/Alamofire

Hello, here's my code :

                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)

        }

I need to know how to convert the destination path (destination) to filePath or how to get the download file in the response call back ?

question

Most helpful comment

Nevermind, I finally wrapped my head around these closures.

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

However, I can't understand why you are working with closures to set a download url. Seems like overkill.

All 10 comments

It's a bit tricky if you use the suggestedDownloadDestination method.

If you use the suggestedDownloadDestination method to retrieve the destination closure, you'll need to pass the response to the destination closure in your response closure to figure out where the file was moved.

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

This should always give you the right value, as long as your directory and domain are valid on iOS. If not, you'll get the temporary location which is actually accurate as well. If you truly want full control over where the file is moved to, don't use the suggestedDownloadDestination method and use your own custom destination closure that returns the fileURL you want.

@cnoon
I 've tried this :

    func filePath() -> NSURL{
        let documentDirectoryUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0];
        let folderPath = documentDirectoryUrl.URLByAppendingPathComponent("Nawader/");
        let fileName = fileUrl!.lastPathComponent;
        let filePath = folderPath.URLByAppendingPathComponent(fileName!);
        return filePath;
    }

    func downloadFile(){
        let destination: (NSURL, NSHTTPURLResponse) -> (NSURL) = {
            (temporaryUrl, response)  in
            if response.statusCode == 200 {
                return self.filePath();
            }
            else {
                return temporaryUrl
            }
        }


        Alamofire.download(.GET, (fileUrl?.path)!, destination:destination)
            .progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
                print("\(totalBytesRead) / \(totalBytesExpectedToRead) \n")
            }
            .response { request, response, _, error in
                print(response)
        }
    }

But I get this error at Alamofire.download line :

fatal error: unexpectedly found nil while unwrapping an Optional value

Do you have any idea what's wrong ?

I' resolved this problem it was caused by (fileUrl?.path)! not by destination function as I thought first time

@cnoon after downloading finished when I check if file exist at the given path I can't find it.
Header when finishing download :

Optional(<NSHTTPURLResponse: 0x7fca1b230910> { URL: https://dl.dropboxusercontent.com/u/70441529/NWADER%20-%2023.pdf } { status code: 200, headers {
    "Accept-Ranges" = bytes;
    "Cache-Control" = "max-age=0";
    "Content-Disposition" = "inline; filename=\"NWADER - 23.pdf\"; filename*=UTF-8''NWADER%20-%2023.pdf";
    "Content-Length" = 75449827;
    "Content-Type" = "application/pdf";
    Date = "Sat, 07 Nov 2015 12:27:46 GMT";
    Etag = 2894n;
    Pragma = public;
    Server = nginx;
    "Set-Cookie" = "uc_session=frshBchxeZ34Ln9tiirQoBO4kq9zIkqvaHq9jaaO9EL0e4jJmkDtltTKx6oPj3XL; Domain=dropboxusercontent.com; httponly; Path=/; secure";
    "content-security-policy" = "; referrer no-referrer;";
    "x-content-security-policy" = "; referrer no-referrer;";
    "x-dropbox-request-id" = c24b832d5e45aab36abaaf5e809670b8;
    "x-robots-tag" = "noindex, nofollow, noimageindex";
    "x-server-response-time" = 516;
    "x-webkit-csp" = "; referrer no-referrer;";
} })

do you have an idea why I can't find the downloaded file ?

The downloaded file path isn't going to be in the header. You need to load the data using the NSData initializer to load the contents of fileURL. Then you'll be in business.

@cnoon Thanks!

you'll need to pass the response to the destination closure in your response closure to figure out where the file was moved.

Say again??? pass response to destination? How?

If I start typing destination( the code completion gives me nothing useful. So it doesn't seem like I can pass something to destination

Nevermind, I finally wrapped my head around these closures.

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

However, I can't understand why you are working with closures to set a download url. Seems like overkill.

The issue for me was that the file is downloaded but then moved to temp location, not the one I passed, and that due to the path is not valid a folder missing so I had to create that folder before

The file isn't moved into the temp location @chlebta, that's where the data is written while the download is in progress. Once completed, it will attempt to move the new file to the location provided in the destination closure. You need to make sure your folder structure is in place before attempting to move the temp file to it's final location.

Was this page helpful?
0 / 5 - 0 ratings