如何将选定的文件复制到应用程序的目录

How to copy selected file to app's directory

我是 iOS 中 FileManager 的新手。 我正在尝试创建一个简单的应用程序:有一个文件列表,当用户按下一个单元格时,该文件将打开。用户还可以添加新文件。

这是我目前拥有的:

class TableViewController: UITableViewController, UIDocumentPickerDelegate {

var urls: [URL] = []

override func viewDidLoad() {
    super.viewDidLoad()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem
}

@IBAction func newButtonPressed(_ sender: Any) {
    let types = UTType(tag: "pdf", tagClass: .filenameExtension, conformingTo: nil)!
    let controller = UIDocumentPickerViewController(forOpeningContentTypes: [types])
    controller.delegate = self
    self.present(controller, animated: true, completion: nil)
}

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
    for url in urls {
        self.storeAndShare(withURL: url)
    }
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return urls.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: .default, reuseIdentifier: nil)

    cell.textLabel?.text = urls[indexPath.row].localizedName

    return cell
}

lazy var documentInteractionController: UIDocumentInteractionController = {
    let vc = UIDocumentInteractionController()
    vc.delegate = self
    return vc
}()

func share(url: URL) {
    documentInteractionController.url = url
    documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
    documentInteractionController.name = url.localizedName ?? url.lastPathComponent
    documentInteractionController.presentPreview(animated: true)
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    share(url: self.urls[indexPath.row])
}

func storeAndShare(withURL url: URL) {
    /// START YOUR ACTIVITY INDICATOR HERE
    URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else { return }
        let direcotryURL = URL(string: FileManager.default.currentDirectoryPath)!
        let newURL = direcotryURL.appendingPathComponent(response?.suggestedFilename ?? "fileName.pdf")
        
        do {
            try data.write(to: newURL)
        } catch let err {
            print("ERROR: \(err).")

            // Error Domain=NSCocoaErrorDomain Code=518 "The file couldn’t be saved because the specified URL type isn’t supported." UserInfo={NSURL=/doc.pdf}

            return
        }
        
        DispatchQueue.main.async {
            /// STOP YOUR ACTIVITY INDICATOR HERE
            self.urls.append(newURL)
            self.share(url: newURL)
            self.tableView.reloadData()
        }
        }.resume()
}

}

extension TableViewController: UIDocumentInteractionControllerDelegate {
/// If presenting atop a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform
func documentInteractionControllerViewControllerForPreview(_ controller:  UIDocumentInteractionController) -> UIViewController {
    guard let navVC = self.navigationController else {
        return self
    }
    return navVC
}
}
extension URL {
var typeIdentifier: String? {
    return (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier
}
var localizedName: String? {
    return (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName
}
}

我在使用 storeAndShare() 功能时遇到问题。我试图将选定的文件复制到应用程序的目录,然后将新的 URL 添加到 urls 列表 (self.urls)。 但它不起作用,并在 data.write:

中给我一个错误

Error Domain=NSCocoaErrorDomain Code=518 "The file couldn’t be saved because the specified URL type isn’t supported." UserInfo={NSURL=/doc.pdf}

为什么会这样?我怎样才能达到我的需要?提前致谢

最严重的错误是currentDirectoryPath。您不能使用它来获取 Documents 目录的路径。您必须调用 url(for:in:appropriateFor:create:urls(for:in:)FileManager

而且 - 如果我们谈论的是本地文件 - URLSession 也是错误的方式。

func storeAndShare(with url: URL) {

    let directoryURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    let newURL = directoryURL.appendingPathComponent(url.lastPathComponent)
    
    do {
        try FileManager.default.copyItem(at: url, to: newURL)
        DispatchQueue.main.async {
            self.urls.append(newURL)
            self.share(url: newURL)
            self.tableView.reloadData()
        }
    } catch {
        print("ERROR: \(error).")
    }
}

"/doc.pdf"

对你来说是不可写的。

获取文档目录:

let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

并将文件保存在那里(而不是使用 currentDirectoryPath)。