The first view of my app (Swift 5, Xcode 10, iOS 12) has a "username" TextField
and a "login" Button
. Clicking on the button checks if there's a file for the entered username on my FTP server and downloads it to the Documents
folder on the device. For this I'm using FileProvider.
My code:
private func download() {
print("start download") //Only called once!
let foldername = "myfolder"
let filename = "mytestfile.txf"
let server = "192.0.0.1"
let username = "testuser"
let password = "testpw"
let credential = URLCredential(user: username, password: password, persistence: .permanent)
let ftpProvider = FTPFileProvider(baseURL: server, mode: FTPFileProvider.Mode.passive, credential: credential, cache: URLCache())
ftpProvider?.delegate = self as FileProviderDelegate
let fileManager = FileManager.default
let source = "/\(foldername)/\(filename)"
let dest = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(filename)
let destPath = dest.path
if fileManager.fileExists(atPath: destPath) {
print("file already exists!")
do {
try fileManager.removeItem(atPath: destPath)
} catch {
print("error removing!") //TODO: Error
}
print("still exists: \(fileManager.fileExists(atPath: destPath))")
} else {
print("file doesn't already exist!")
}
let progress = ftpProvider?.copyItem(path: source, toLocalURL: dest, completionHandler: nil)
progressBar.observedProgress = progress
}
I'm checking if the file already exists on the device because FileProvider
doesn't seem to provide a copyItem
function for downloading that also lets you overwrite the local file.
The problem is that copyItem
tries to do everything twice: Downloading the file the first time succeeds (and it actually exists in Documents
, I checked) because I manually delete the file if it already exists. The second try fails because the file already exists and this copyItem
function doesn't know how to overwrite and of course doesn't call my code to delete the original again.
What can I do to fix this?
Edit/Update:
I created a simple "sample.txt" at the root of my ftp server (text inside :"Hello world from sample.txt!"), then tried to just read the file to later save it myself. For this I'm using this code from the "Sample-iOS.swift" file here.
ftpProvider?.contents(path: source, completionHandler: {
contents, error in
if let contents = contents {
print(String(data: contents, encoding: .utf8))
}
})
But it also does this twice! The output for the "sample.txt" file is:
Optional("Hello world from sample.txt!")
Fetching on sample.txt succeed.
Optional("Hello world from sample.txt!Hello world from sample.txt!")
Fetching on sample.txt succeed.
Why is it calling this twice too? I'm only calling my function once and "start download" is also only printed once.
Edit/Update 2:
I did some more investigating and found out what's called twice in the contents
function:
- It's the whole
self.ftpDownload
section! - And inside FTPHelper.ftpLogin the whole
self.ftpRetrieve
section is called twice. - And inside FTPHelper.ftpRetrieve the whole
self.attributesOfItem
section is called twice. - And probably so on...
ftpProvider?.copyItem
uses the same ftpDownload
func, so at least I know why both contents()
and copyItem()
are affected.
The same question remains though: Why is it calling these functions twice and how do I fix this?