如何获取用户库或相机中所选照片的​​ URL?

GBM*_*BMR 5 swift

我有一个应用程序,用户可以在其中选择是要拍照还是从他们的库中选择一张照片。我拥有的代码获取了 Xcode 设备模拟器的图像 URL,但不适用于我的物理 iPhone。当我使用个人设备选择图像时 我的结果会打印出来

Failed: There is a client side validation error for the field [local] with message: The file located at the `local` URL is missing. Make sure the file exists before uploading to storage.
Run Code Online (Sandbox Code Playgroud)

但是当我使用设备模拟器运行时,它运行完美,图像存储在我的后端。我不确定为什么会发生这种情况。

我希望能够从我自己的设备获取 URL。

从 xcode 设备模拟器打印的 url

file:///Users/GBMR/Library/Developer/CoreSimulator/Devices/877A8184-D857-4211-94B1-00A6B724A956/data/Containers/Data/Application/094279FA-37B1-45E6-ABC4-ADAA08B5477B/PicturesB71286E4-1994-4D76-AC14-D40A062BC832.jpeg
Completed: ywassupo
Run Code Online (Sandbox Code Playgroud)

从我的物理 iPhone 打印的 url

file:///var/mobile/Containers/Data/Application/C0415B3C-F50E-4D20-8D8A-941D29B9C4D1/Pictures9BA481F9-C52A-40FD-8A06-AAA2D6CDA6D7.jpeg
Failed: There is a client side validation error for the field [local] with message: The file located at the `local` URL is missing. Make sure the file exists before uploading to storage.
Run Code Online (Sandbox Code Playgroud)

代码:

  func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

        if let selectedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
            imageView.image = selectedImage
            imageView.contentMode = .scaleAspectFit

            //            detect(image: ciimage)
            navigationItem.title = "Tap next to continue"
            nextButton.isEnabled = true

            if let imgUrl = info[UIImagePickerController.InfoKey.imageURL] as? URL{
                let imgName = imgUrl.lastPathComponent
                let documentDirectory = NSSearchPathForDirectoriesInDomains(.picturesDirectory, .allDomainsMask, true).first
                let localPath = documentDirectory?.appending(imgName)

                //let image = info[UIImagePickerController.InfoKey] as! UIImage
                let data = selectedImage.pngData()! as NSData
                data.write(toFile: localPath!, atomically: true)
                //let imageData = NSData(contentsOfFile: localPath!)!
                let photoURL = URL.init(fileURLWithPath: localPath!)
                let infoTVC = InfoTableViewController()
                infoTVC.imageChosenName = photoURL
                _ = Amplify.Storage.uploadFile(key: "ywassupo", local: photoURL ,resultListener: {(event) in
                    switch event{
                    case .success(let data):
                        print("Completed: \(data)")
                    case .failure(let storageError):
                        print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
                    }

                })
                //NSURL(fileURLWithPath: localPath!)
                print(photoURL)

                dismiss(animated:true, completion: nil)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

任何人都可以将我引导到正确的方向来解决这个问题吗?

Rob*_*Rob 2

您没有正确构建路径。有几个问题:

\n\n
    \n
  1. 您只需将文件名附加到图片路径字符串中即可。您\xe2\x80\x99 在文件夹和文件名之间缺少斜杠。显然,您可以自己添加此内容,但为了将来的参考,如果您使用 URL,它会为您添加必要的斜杠。

  2. \n
  3. 此 \xe2\x80\x9cpictures\xe2\x80\x9d 目录不适用于 iOS。I\xe2\x80\x99d 建议使用不同的文件夹。也许将其复制到临时目录中的文件夹中,从那里上传,然后在\xe2\x80\x99完成后进行清理。

  4. \n
  5. 如果您想知道为什么您的代码可以在模拟器上运行,但不能在设备上运行,那是因为前者不会强制执行沙箱规则,而后者会强制执行。

  6. \n
\n\n
\n\n

顺便说一句,除非必要,否则我建议避免通过 a 绊倒 xe2x80x9d UIImage。上面,我们\xe2\x80\x99正在处理原始资产,但如果您创建一个UIImage, 只是为了提取 JPG 或 PNG 表示,您\xe2\x80\x99将丢失有关资产的信息,并可能使资产变得更大比它需要的要多。只需获取图像 URL、复制该文件并上传,\xe2\x80\x99 的效率要高得多:

\n\n
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {\n    guard let imageUrl = info[.imageURL] as? URL else {\n        return\n    }\n\n    do {\n        let tempDirectory = URL(fileURLWithPath: NSTemporaryDirectory())\n            .appendingPathComponent("uploads")\n\n        try FileManager.default.createDirectory(at: tempDirectory, withIntermediateDirectories: true, attributes: nil)\n\n        let fileURL = tempDirectory\n            .appendingPathComponent(UUID().uuidString)\n            .appendingPathComponent(imageUrl.pathExtension)\n\n        try FileManager.default.copyItem(at: imageUrl, to: fileURL)\n\n        // when done, clean up (presumably in the completion handler of the async upload routine)\n\n        try FileManager.default.removeItem(at: fileURL)\n    } catch {\n        print(error)\n    }\n\n    dismiss(animated: true)\n}\n
Run Code Online (Sandbox Code Playgroud)\n