FileProvider: "CopyItem()" вызывается дважды -> ошибка (загрузка по FTP)
Первый вид моего приложения (Swift 5, Xcode 10, iOS 12) имеет "имя пользователя" TextField
и "логин" Button
, Нажатие на кнопку проверяет, есть ли файл для введенного имени пользователя на моем FTP-сервере, и загружает его на Documents
папка на устройстве. Для этого я использую FileProvider.
Мой код:
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
}
Я проверяю, существует ли файл на устройстве, потому что FileProvider
кажется, не обеспечивает copyItem
функция для загрузки, которая также позволяет перезаписать локальный файл.
Проблема в том, что copyItem
пытается сделать все дважды: загрузка файла в первый раз удалась (и он действительно существует в Documents
Я проверил), потому что я вручную удаляю файл, если он уже существует. Вторая попытка не удалась, потому что файл уже существует, и это copyItem
функция не знает, как перезаписать и, конечно, не вызывает мой код, чтобы снова удалить оригинал.
Что я могу сделать, чтобы это исправить?
Редактировать /Update:
Я создал простой "sample.txt" в корне моего ftp-сервера (текст внутри:"Hello world from sample.txt!"), А затем попытался просто прочитать файл, чтобы позже сохранить его сам. Для этого я использую этот код из файла "Sample-iOS.swift" здесь.
ftpProvider?.contents(path: source, completionHandler: {
contents, error in
if let contents = contents {
print(String(data: contents, encoding: .utf8))
}
})
Но это также делает это дважды! Выходные данные для файла "sample.txt":
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.
Почему он тоже дважды это называет? Я вызываю свою функцию только один раз, и "начало загрузки" также печатается только один раз.
Редактировать / обновить 2:
Я сделал еще несколько расследований и выяснил, что называется дважды в contents
функция:
- Это целое
self.ftpDownload
раздел! - А внутри FTPHelper.ftp Логин весь
self.ftpRetrieve
раздел вызывается дважды. - А внутри FTPHelper.ftp восстановить всю
self.attributesOfItem
раздел вызывается дважды. - И, наверное, так далее...
ftpProvider?.copyItem
использует то же самое ftpDownload
func, так что, по крайней мере, я знаю, почему оба contents()
а также copyItem()
находятся под влиянием.
Однако остается тот же вопрос: почему он вызывает эти функции дважды и как мне это исправить?
0 ответов
Это не ответ, который показывает фактическое исправление для FileProvider!
К сожалению, в настоящее время библиотека довольно глючная, функции вызываются дважды (что можно отчасти предотвратить, используя проверку bool firstTimeCalled), и если сервер работает медленно (-ish), вы также можете не получить, например, полный список файлов. в каталоге, потому что FileProvider перестает получать ответы до того, как сервер фактически завершил работу.
Я не нашел никаких других библиотек FTP для Swift, которые бы работали (и все еще поддерживаются), поэтому теперь я использую BlueSocket (который может открывать сокеты, отправлять команды на сервер и получать команды от него) и собирать свои собственные небольшая библиотека, которая может отправлять / получать,... файлы (используя коды FTP) вокруг него.