filePicker.swift 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import Foundation
  2. import UIKit
  3. import MobileCoreServices
  4. // UTS内置对象的引用
  5. import DCloudUTSFoundation
  6. @objc public class NativeCode: NSObject {
  7. /// 当前视图控制器,用于弹出文件选择器
  8. @objc static var currentViewController: UIViewController?
  9. /// 文件选择器代理对象
  10. private static var filePickerDelegate: FilePickerDelegate?
  11. /// 打开文件选择器
  12. @objc static func openFilePicker(_ callback: @escaping (_ fileURL: String?, _ size: Int) -> Void) {
  13. // 确保当前视图控制器存在
  14. guard let viewController = currentViewController else {
  15. callback(nil, 0)
  16. return
  17. }
  18. // 创建文件选择器
  19. let documentPicker = UIDocumentPickerViewController(documentTypes: [String(kUTTypeData)], in: .open)
  20. filePickerDelegate = FilePickerDelegate(callback: callback) // 强引用持有 delegate
  21. documentPicker.delegate = filePickerDelegate
  22. documentPicker.modalPresentationStyle = .formSheet
  23. // 在主线程中执行 UI 操作
  24. DispatchQueue.main.async {
  25. // 弹出文件选择器
  26. viewController.present(documentPicker, animated: true, completion: nil)
  27. }
  28. }
  29. }
  30. // MARK: - 文件选择器代理
  31. class FilePickerDelegate: NSObject, UIDocumentPickerDelegate {
  32. private var callback: (_ fileURL: String?, _ size: Int) -> Void
  33. init(callback: @escaping (_ fileURL: String?, _ size: Int) -> Void) {
  34. self.callback = callback
  35. }
  36. func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
  37. // 用户选择了文件
  38. console.log(urls);
  39. if let fileURL = urls.first {
  40. // 1. 获取安全访问权限
  41. let accessing = fileURL.startAccessingSecurityScopedResource()
  42. do {
  43. // 2. 将文件复制到应用的临时目录(获取可用的文件路径)
  44. let tempDirectoryURL = FileManager.default.temporaryDirectory
  45. let destinationURL = tempDirectoryURL.appendingPathComponent(fileURL.lastPathComponent)
  46. // 删除已存在的文件(如果有)
  47. if FileManager.default.fileExists(atPath: destinationURL.path) {
  48. try FileManager.default.removeItem(at: destinationURL)
  49. }
  50. // 复制文件到临时目录
  51. try FileManager.default.copyItem(at: fileURL, to: destinationURL)
  52. // 3. 获取文件属性
  53. let fileAttributes = try destinationURL.resourceValues(forKeys: [.fileSizeKey])
  54. let fileSize = fileAttributes.fileSize ?? 0
  55. // 在主线程中执行回调
  56. DispatchQueue.main.async {
  57. console.log(destinationURL.relativePath);
  58. self.callback(destinationURL.path, fileSize) // 返回文件路径 path relativePath absoluteString
  59. }
  60. } catch {
  61. console.log("Error getting file size: \(error.localizedDescription)")
  62. // DispatchQueue.main.async {
  63. // self.callback(nil, 0)
  64. // }
  65. }
  66. // 4. 释放访问权限
  67. if accessing {
  68. fileURL.stopAccessingSecurityScopedResource()
  69. }
  70. } else {
  71. DispatchQueue.main.async {
  72. self.callback(nil, 0)
  73. }
  74. }
  75. }
  76. func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
  77. // 用户取消了文件选择
  78. // self.callback(nil, 0)
  79. }
  80. }