如何从 Swift 4.2 中的共享 Dropbox link 读取文本文件的内容(无需下载)?

How do I read a text-file's content from it's shared Dropbox link in Swift 4.2 (without downloading)?

我很难弄清楚如何通过 Swift 4.2 从共享 Dropbox link(无需下载)输出简单文本文件的内容。

例如:

let url = URL(string: "https://www.dropbox.com/s/rokwv82h54ogwy1/test.txt?dl=0")!
// the dropbox link above is a shared link so anyone can view it
    
do {
                
    let content = try String(contentsOf: url)
    print("File Content:   \(content)")
} catch let error as NSError {
                
    print("\(error)")
}

当我 运行 这个代码时,我得到这个错误:

Error Domain=NSCocoaErrorDomain Code=260 “文件“test.txt”无法打开,因为没有这样的文件。”(还有更多错误但很大)

有人能帮帮我吗?谢谢

There's more to the error but it's quite big

不要去除错误信息。如果你不知道如何解决这个问题,你可能不知道要剥离什么来保持它的价值。

如何解决您的问题

  • Select目标
  • 切换到签名和功能 选项卡
  • App Sandbox - 网络 - 启用传出连接(客户端)

  • 将 URL (dl=0) 更改为 (dl=1)
    • 0 = 显示带有预览和下载的网页 link
    • 1 = 不显示任何网页,只提供文件
let url = URL(string: "https://www.dropbox.com/s/rokwv82h54ogwy1/test.txt?dl=1")!
// Change dl=0 to dl=1                                                       ^
    
do {
    let content = try String(contentsOf: url)
    print("File Content: \(content)")
} catch let error as NSError {
    print("\(error)")
}

运行 一次,你会得到:

File Content:   
This is a test. If you can read this, you have passed! :)

不要使用String(contentsOf: url),因为它不是异步的,它会阻塞主线程(UI)。

异步示例 - 假设您有一个带有一个文本字段(标签)的视图控制器,并且您想在那里显示文件内容:

import Cocoa

class ViewController: NSViewController {
    @IBOutlet var textField: NSTextField!
    
    override func viewWillAppear() {
        super.viewWillAppear()
        textField.stringValue = "Loading ..."
        loadRemoteFile()
    }
    
    func loadRemoteFile() {
        let url = URL(string: "https://www.dropbox.com/s/rokwv82h54ogwy1/test.txt?dl=1")!
        
        let task = URLSession.shared.dataTask(with: url) { data, _, error in
            // Following code is not called on the main thread. If we'd like to
            // modify UI elements, we have to dispatch our code on the main thread.
            // Hence the DispatchQueue.main.async {}.
            
            if let error = error {
                print("Failed with error: \(error)")
                DispatchQueue.main.async { self.textField.stringValue = "Failed" }
                return
            }

            guard let data = data,
                  let content = String(data: data, encoding: .utf8) else {
                print("Failed to decode data as an UTF-8 string")
                DispatchQueue.main.async { self.textField.stringValue = "Failed" }
                return
            }
            
            print("Content: \(content)")
            DispatchQueue.main.async { self.textField.stringValue = content }
        }
        
        // At this point, we have a task which will download the file, but the task
        // is not running. Every task is initially suspended.
        
        task.resume() // Start the background task
        
        // At this point, your program normally continues, because the download
        // is executed in the background (not on the main thread).
    }
}