问题
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?
回答1:
This isn't an answer that shows an actual fix for FileProvider!
Unfortunately the library is pretty buggy currently, with functions being called twice (which you can kind of prevent by using a "firstTimeCalled" bool check) and if the server's slow(-ish), you also might not get e.g. the full list of files in a directory because FileProvider stops receiving answers before the server's actually done.
I haven't found any other FTP libraries for Swift that work (and are still supported), so now I'm using BlueSocket (which is able to open sockets, send commands to the server and receive commands from it) and built my own small library that can send/receive,... files (using the FTP codes) around it.
来源:https://stackoverflow.com/questions/56113593/fileprovider-copyitem-is-called-twice-error-ftp-download