SWIFTUI - 尝试从 OneDrive 和 GoogleDrive 等云文件提供商导入文件时出现文件未找到错误
Posted
技术标签:
【中文标题】SWIFTUI - 尝试从 OneDrive 和 GoogleDrive 等云文件提供商导入文件时出现文件未找到错误【英文标题】:SWIFTUI - File Not Found error when trying to import a file from a cloud file provider like OneDrive and GoogleDrive 【发布时间】:2021-04-23 14:26:30 【问题描述】:我有以下 SwiftUI 代码,其中一个简单的按钮会打开 ios 文件管理器并允许用户选择要导入的 CSV 文件。我发现它适用于本地存储在我的设备上的文件,但是如果我尝试从 Google Drive 或 OneDrive 中选择一个文件,它会获取一个 URL,但是当我尝试从中检索数据时,它会返回一个错误说找不到文件。
经过一番摸索后,我发现在使用文件浏览器时,如果我长按以调出上下文菜单,然后查看文件的信息(我猜这可能会将其拉到手机本地缓存),然后它将按预期工作。这显示在以下动画 gif 中:
我发现,一旦我完成了缓存技巧,我就可以使用相同的代码在其他应用程序中毫无问题地访问该文件,而且我还发现我可以卸载我的应用程序并重新安装它,它会继续工作。
谁能建议使用 SwiftUI 的方法,在尝试从 Google Drive 或 OneDrive 导入文件时,我可以避免此 File Not Found 错误?
我用来测试的整个代码如下:
import SwiftUI
struct ContentView: View
@State private var isImporting: Bool = false
@State private var fileContentString = ""
@State var alertMsg = ""
@State var showAlert = false
func reportError(error: String)
alertMsg = error
showAlert.toggle()
var body: some View
VStack
Button(action: isImporting = true, label:
Text("Select CSV File")
)
.padding()
Text(fileContentString) //This will display the imported CSV as text in the view.
.padding()
.fileImporter(
isPresented: $isImporting,
allowedContentTypes: [.commaSeparatedText],
allowsMultipleSelection: false
) result in
do
guard let selectedFileURL: URL = try result.get().first else
alertMsg = "ERROR: Result.get() failed"
self.reportError(error: alertMsg)
return
print("selectedFileURL is \(selectedFileURL)")
if selectedFileURL.startAccessingSecurityScopedResource()
//print("startAccessingSecurityScopedResource passed")
do
print("Getting Data from URL...")
let inputData = try Data(contentsOf: selectedFileURL)
print("Converting data to string...")
let inputString = String(decoding: inputData, as: UTF8.self)
print(inputString)
fileContentString = inputString
catch
alertMsg = "ERROR: \(error.localizedDescription)"
self.reportError(error: alertMsg)
print(alertMsg)
//defer selectedFileURL.stopAccessingSecurityScopedResource()
else
// Handle denied access
alertMsg = "ERROR: Unable to read file contents - Access Denied"
self.reportError(error: alertMsg)
print(alertMsg)
catch
// Handle failure.
alertMsg = "ERROR: Unable to read file contents - \(error.localizedDescription)"
self.reportError(error: alertMsg)
print(alertMsg)
.alert(isPresented: $showAlert, content:
Alert(title: Text("Message"), message: Text(alertMsg), dismissButton: .destructive(Text("OK"), action:
))
)
控制台日志输出如下:
selectedFileURL is file:///private/var/mobile/Containers/Shared/AppGroup/8F147702-8630-423B-9DA0-AE49667748EB/File%20Provider%20Storage/84645546/1aTSCPGxY3HzILlCIFlMRtx4eEWDZ2JAq/example4.csv
Getting Data from URL...
ERROR: The file “example4.csv” couldn’t be opened because there is no such file.
selectedFileURL is file:///private/var/mobile/Containers/Shared/AppGroup/8F147702-8630-423B-9DA0-AE49667748EB/File%20Provider%20Storage/84645546/1aTSCPGxY3HzILlCIFlMRtx4eEWDZ2JAq/example4.csv
Getting Data from URL...
Converting data to string...
First Name,Last Name
Luke,Skywalker
Darth,Vader
我的测试是在运行 iOS 14.2 的物理 iPhone 12 Pro Max 和运行 iPadOS 14.4 的物理 iPad Air 2 上完成的。
【问题讨论】:
【参考方案1】:我找到了问题的答案。解决方案是使用 NSFileCoordinator() 来强制下载文件。
使用下面的代码,如果我访问之前未下载到本地设备的云存储中的文件,它将打印“文件不可用”,但它现在只会下载文件而不是抛出未找到的文件错误。
理想情况下,我希望能够先下载文件属性元数据以检查文件有多大,然后再决定是否要下载完整文件。 NSFileCoordinator 有一个仅元数据选项,但我还没有弄清楚如何从中检索和解释结果。现在就可以了...
if selectedFileURL.startAccessingSecurityScopedResource()
let fileManager = FileManager.default
if fileManager.fileExists(atPath: selectedFileURL.path)
print("FILE AVAILABLE")
else
print("FILE NOT AVAILABLE")
var error: NSError?
NSFileCoordinator().coordinate(
readingItemAt: selectedFileURL, options: .forUploading, error: &error) url in
print("coordinated URL", url)
let coordinatedURL = url
isShowingFileDetails = false
importedFileURL = selectedFileURL
do
let resources = try selectedFileURL.resourceValues(forKeys:[.fileSizeKey])
let fileSize = resources.fileSize!
print ("File Size is \(fileSize)")
catch
print("Error: \(error)")
do
print("Getting Data from URL...")
let inputData = try Data(contentsOf: selectedFileURL)
print("Do stuff with file....")
【讨论】:
非常好,尼斯湖水怪。多年来,我一直在为这个问题苦苦挣扎,而您已经找到了解决方案(或者说是一种解决方法)。谢谢。 非常感谢@LochNessMonster!我在这个问题上花了 3 天的时间......你解决了它!以上是关于SWIFTUI - 尝试从 OneDrive 和 GoogleDrive 等云文件提供商导入文件时出现文件未找到错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 在 OneDrive 文件夹中打开 excel 工作簿
尝试使用环境变量从 HostingViewController 呈现 SwiftUI
Evernote 和 OneDrive 的文件选择器 API