ios - FileProvider:“CopyItem()”被调用了两次 -> 错误(FTP 下载)
问题描述
我的应用程序(Swift 5、Xcode 10、iOS 12)的第一个视图有一个 "username"TextField
和一个 "login" 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
函数不知道如何覆盖,当然也不会调用我的代码再次删除原始文件。
我能做些什么来解决这个问题?
编辑/更新:
我在我的 ftp 服务器的根目录中创建了一个简单的“sample.txt”(里面的文本:“来自 sample.txt 的 Hello world!”),然后尝试读取该文件以便以后自己保存。为此,我在这里使用“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.ftpLogin 中,整个
self.ftpRetrieve
部分被调用了两次。 - 在 FTPHelper.ftpRetrieve 中,整个
self.attributesOfItem
部分被调用了两次。 - 大概是这样……
ftpProvider?.copyItem
使用相同的ftpDownload
函数,所以至少我知道为什么两者都会contents()
受到copyItem()
影响。
但同样的问题仍然存在:为什么它两次调用这些函数,我该如何解决这个问题?
解决方案
这不是显示 FileProvider 实际修复的答案!
不幸的是,这个库目前有很多错误,函数被调用了两次(你可以通过使用“firstTimeCalled”布尔检查来防止这种情况),如果服务器很慢(-ish),你也可能无法获得完整的文件列表在目录中,因为 FileProvider 在服务器实际完成之前停止接收答案。
我还没有找到任何其他适用于 Swift 的 FTP 库(并且仍然受支持),所以现在我正在使用BlueSocket(它能够打开套接字、向服务器发送命令并从中接收命令)并构建了我自己的可以发送/接收的小型库,...文件(使用 FTP 代码)在它周围。
推荐阅读
- laravel - 多对多数据透视表上的自定义范围
- flutter - 断言失败:第 19 行第 16 行:'纬度!= null':不正确。颤振错误
- javascript - 我可以用更新的 Object.fromEntries(new FormData(form)) 替换表单元素循环解析吗?
- sql-server - SQL Server:连接到服务器时出现错误 26
- linux - 如何仅在脚本完成后获取多个命令的执行时间?
- laravel - 使用 groupBy 从 mySQL 获取数据时 Laravel 错误
- node.js - AWS 弹性 beanstalk 上的默认代理配置将请求转发到的 Web 应用程序的端口号是多少?
- python - Python函数接受一个字符串,但不是当它在一个变量中
- reactjs - 如何在反应中反序列化ArrayObject的数据
- ubuntu - Rust Ubuntu 20.04.1 安装问题