I am using AlamoFire 5.0 and want to force permanent cache storage of data fetched from urls (.obj files, .png images etc.). Is there some way to ignore/intercept the HTTP headers sent by the server and just force permanent caching?
let destination: DownloadRequest.Destination = { _, _ in
var documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
return (documentsURL, [.removePreviousFile])
}
let request = AF.download("http://someurl.com", to: destination)
request
.response(completionHandler: { (response) in
//handle response data
})
You may want to consider Disk caching your response.
This answer might be of help:
Disk Cache Images
Related
I'm trying to download a file (namely 'xp-en.zip') from a certain server. I've already checked that this file exists using contentsOfDirectory(::), but for some reason, after the download is completed the file doesn't show up in the directory it was supposed to have been copied to. I'm using XCode and I thought it could have something to do with the app's permissions (since the destination directory is .documentDirectory), but I tried changing it to the main bundle to no avail.
I also tried downloading from another server ('speedtest.tele2.net') but it didn't work either.
let credential = URLCredential(user: "anonymous", password: "123456", persistence: .permanent)
let fileManager = FileManager.default
func FTPDownloadUpload(download: Bool = true, server: String, path: String){
let localFilePath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
guard let url = URL(string: server) else{
print("Invalid URL")
return
}
let FTPProvider = FTPFileProvider(baseURL: URL(string: "ftp://" + server)!, mode: .passive, credential: credential, cache: URLCache())
if download{
FTPProvider?.copyItem(path: "/" + path, toLocalURL: localFilePath, completionHandler: {x in print("Download completed")})
//I know this completionHandler closure kinda sucks but I don't know what else to put inside it. Keep in mind my program doesn't have anything to do after calling this function
}else{
//This is the upload section. Didn't include it to keep the code shorter
}
}
My function call is:
FTPDownloadUpload(server: "176.74.128.88", path: "xp-en.zip")
This question already has an answer here:
UIImage(contentsOfFile:) returning nil despite file existing in caches directory [duplicate]
(1 answer)
Closed 4 years ago.
I have the following swift function that I hoped would save incoming bytes to a JPEG file on iOS. Unfortunately an exception is thrown by the call to data.write and I get the error message
The folder “studioframe0.jpg” doesn’t exist. writing to file:/var/mobile/Containers/Data/Application/2A504F84-E8B7-42F8-B8C3-3D0A53C1E11A/Documents/studioframe0.jpg -- file:///
Why does iOS think it is a directory path to a directory which does not exist as opposed to a file that I am asking it to write?
func saveToFile(data: Data){
if savedImageCount < 10 {
guard let documentDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("studioframe\(savedImageCount).jpg").absoluteString)
savedImageCount += 1
do {
try data.write(to: imgPath, options: .atomic)
print("Saved \(imgPath) to disk")
} catch let error {
print("\(error.localizedDescription) writing to \(imgPath)")
}
}
}
URL(fileURLWithPath together with absoluteString is wrong.
You would have to write (note the different URL initializer):
let imgPath = URL(string: documentDirectoryPath.appendingPathComponent("studioframe\(savedImageCount).jpg").absoluteString)
but this (URL → String → URL) is very cumbersome, there is a much simpler solution, please consider the difference between (string) path and URL
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // the Documents directory is guaranteed to exist.
let imgURL = documentDirectoryURL.appendingPathComponent("studioframe\(savedImageCount).jpg")
...
try data.write(to: imgURL, options: .atomic)
In my iOS project I'm using Alamofire library to download remote documents (from a server with Basic Auth) in this way:
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL = documentsURL.appendingPathComponent("foo.pdf")
return (filePath.url, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(myUrlRequest, to: destination).authenticate(user: user, password: password, persistence: .none).validate().response { response in
print(response)
if response.error == nil, let path = response.destinationURL?.path {
print(path)
}
}
This works great! The file is correctly downloaded in the app's Documents folder.
My problem is when user or/and password are wrong. In this case server response status is 401 Unauthorized and .validate() method correctly fails, but in my Documents folder I find the file "foo.pdf" where the content is a xml that explains the 401 error. What I would like is the file saved only if the validate doesn't fail.
My questions: is there a way, with Alamofire, to save the file just in case the response is validated? Or do I have to manually delete the file when validate fails?
I am having the similar issue at the moment. So far, the only thing I could think of is crude
if response.error != nil {
try? FileManager.default.removeItem(at: destinationURL)
}
in response closure.
I will investigate further though.
EDIT 1:
It seems this issue quite some time ago brought this behaviour https://github.com/Alamofire/Alamofire/issues/233
Currently I have an iOS app that pulls prices and data from websites. So far its been working well, but I want to make it more accurate. To do so, I need to set the cookies for the URL request that I'm currently using String(contentsOf: _) for.
Current Process
let requestUrl: URL = URL(string: "http://www.samsclub.com/sams/search/searchResults.jsp?searchTerm=Apple")!
var content: String?
do {
content = try String(contentsOf: requestUrl)
} catch {
print("Error while converting an NSURL to String: \(error)")
}
if content != "" {
// I do things with the content of the requestUrl...
}
Could Use?
I thought that maybe I should use Alamofire instead to pull those website, and then parse the data.
I need to set the cookie that changes the store number to search, but have been unable to find a way to do so. Bellow is the code I have for pulling the websites data without setting a cookie.
let requestUrl: String = "http://www.samsclub.com/sams/search/searchResults.jsp?searchTerm=Apple"
Alamofire.request(requestUrl, method: .post).responseString { response in
if let content: String = response.result.value {
// I do things with the content of the requestUrl...
}
}
Other Claims
I have found many different ways to set cookies through Alamofire that don't work, but if Alamofire isn't the way to do it, please inform me. I really need this to work, and I'm open to any and every suggestion.
It took four weeks to the day, but I figured it out! URLRequest and Alamofire were my glorious answers!
Create the URL to call.
let requestUrl: String = "http://www.samsclub.com/sams/search/searchResults.jsp?searchTerm=Apple"
Next make the URLRequest with the URL string, and set its http method.
var urlRequest = URLRequest(url: requestUrl)
urlRequest.httpMethod = "POST"
Then set the cookies for the URLRequest.
urlRequest.setValue("myPreferredClub=4969", forHTTPHeaderField: "Cookie")
urlRequest.httpShouldHandleCookies = true
Finally send the URLRequest with Alamofire, and use the response data in whatever way I wish.
Alamofire.request(urlRequest).responseString { response in
if let content: String = response.result.value {
// I do things with the content of the urlRequest...
}
}
I'm struggling to get an image file loaded in Swift 3.
Here is the code:
do {
let imageData = try Data(contentsOf: imageUrl2.asURL())
} catch {
print ("loading image file error")
}
And the current Url String is:
file:///Users/veikoherne/Library/Developer/CoreSimulator/Devices/889A08D5-B8CC-458C-99FF-643A4BA1A806/data/Containers/Data/Application/F64ED326-7894-4EE7-AA3B-B1BB10DF8259/Documents/img2017-03-23 17:39:24.jpg
and obviously I have checked that this file exists and is valid image. It always ends up telling me "loading image file error". Anyone have experiences loading local data in Swift 3?
The answer mentioned was using NSData object and probably Swift 2. Current Swift 3 refuses to bridge NSData to Data, that's why I have to use Data.
Loading data from local file you should use "contentsOfFile:" method.
Reference link: https://www.hackingwithswift.com/example-code/strings/how-to-load-a-string-from-a-file-in-your-bundle
So in case of reading data you can use:
Data(contentsOf: <URL>, options: <Data.ReadingOptions>)
Reading a plain text as a String, use:
String(contentsOfFile: <LocalFileDirPath>)
Reading an image from document directory, use:
UIImage(contentsOfFile: <LocalFileDirPath>)
Hope this would be helpful!
I experienced the same issue when trying to retrieve a file that I just downloaded. If you have saved a file from some url like I did, this should work:
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let localUrl = documentDirectory.appendingPathComponent("somefile.txt")
if FileManager.default.fileExists(atPath: localUrl.path){
if let cert = NSData(contentsOfFile: localUrl.path) {
return cert as Data
}
}
Swift 5 version.
func loadFileFromLocalPath(_ localFilePath: String) ->Data? {
return try? Data(contentsOf: URL(fileURLWithPath: localFilePath))
}