【问题标题】:Value of type 'StorageMetadata' has no member 'downloadURL'“StorageMetadata”类型的值没有成员“downloadURL”
【发布时间】:2018-10-21 05:14:24
【问题描述】:

我刚刚将 Firebase 存储更新到 5.0.0,看起来 metadata.downloadURL() 不再被识别。 (Value of type 'StorageMetadata' has no member 'downloadURL')

虽然在查看文档后它应该仍然可用:

https://firebase.google.com/docs/reference/swift/firebasestorage/api/reference/Classes/StorageMetadata#/c:objc(cs)FIRStorageMetadata(im)downloadURL

该项目已经清理和重建。

我错过了什么吗?

【问题讨论】:

    标签: swift xcode firebase swift4 firebase-storage


    【解决方案1】:
    Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
            if error != nil {
                print(error as Any)
                return
            }
            guard let uid = user?.user.uid else {
                return
            }
    
            self.dismiss(animated: true, completion: nil)
            //Добавляем картинку в firebase. Надо добавить в Pods file pod 'Firebase/Storage' и запустить терминал
            let imageName = NSUUID().uuidString
            let storageRef = Storage.storage().reference()
    
            // Create a reference to the file you want to download
            let starsRef = storageRef.child("profile_images").child("\(imageName).png")
    
            let uploadData = self.profileImageView.image?.pngData()
    
            starsRef.putData(uploadData!, metadata: nil, completion: { (metadata, error) in
                if error != nil {
                    print(error as Any)
                }
                if let profileImageUrl = metadata?.path {
                    let values = ["name": name, "email": email, "profileImage": profileImageUrl]
                    self.registerUserIntoDatabaseWithUID(uid: uid, values: values)
                }
            })
        }
    

    【讨论】:

    • 请补充说明。
    【解决方案2】:

    让我们在 Swift 4.2 中试试这段代码:

    let imgData = UIImage.jpegData(self.imageView.image!)
    
    let imageName = UUID().uuidString
    let ref = Storage.storage().reference().child("pictures/\(imageName).jpg")
    let meta = StorageMetadata()
    meta.contentType = "image/jpeg"
    
    self.uploadToCloud(data: imgData(0.5)!, ref: ref, meta: meta)
    

    UploadToCloud 方法:

    ` Method UploadToCloud
    func uploadToCloud(data:Data, ref:StorageReference, meta:StorageMetadata) {
        ref.putData(data, metadata: meta) { (metaData, error) in
            if let e = error {
                print("==> error: \(e.localizedDescription)")
            }
            else 
            {
                ref.downloadURL(completion: { (url, error) in
                    print("Image URL: \((url?.absoluteString)!)")
                })
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您在将 URL 转换为字符串时遇到困难……您可以试试这个

      url.absoluteString
      

      【讨论】:

        【解决方案4】:

        所有语言搜索都会弹出此问题。因此,对于 Kotlin,解决方案如下:

        val photoRef = FirebaseStorage.getInstance()
                        .reference.child("images/stars.jpg")
        
        // Code ommited - Do some saving - putFile
        
            photoRef.downloadUrl.addOnSuccessListener({ uri ->
                                 product.imageUrl = uri.toString()
                             })
        

        但是,这不是一个好的解决方案。您最好保存路径,然后根据需要重新构建完整的 Url。例如:

        photoRef.downloadUrl.addOnSuccessListener({ uri ->  
                    val imagePath = uri.toString()
                    // Save to database
                })
        

        现在,您可以稍后使用它,而且只能按需使用:

        FirebaseStorage.getInstance().reference.child(product.imageUrl).downloadUrl
                            .addOnSuccessListener { uri ->
                                String imageUrl = uri.toString()
                                // Load in images
                            }
        

        【讨论】:

          【解决方案5】:

          这是我的 Swift 3 / Swift 4 版本。

          解释代码中发生的事情。

          这与 Sh_Khan 的答案基本相同。但在他的示例中,用户已经知道存储桶路径。在我的示例中,我们从上传任务中获取路径。这就是导致我提出这个问题的原因,也是我认为 op 在寻找 metadata.downloadURL() 替代品时正在寻找的东西。

          class StorageManagager {
          
          
              private let storageReference: StorageReference
          
              init() {
          
                  // first we create a reference to our storage
                  // replace the URL with your firebase URL
                  self.storageReference = Storage.storage().reference(forURL: "gs://MYAPP.appspot.com")
              }
          
              // MARK: - UPLOAD DATA
              open func uploadData(_ data: Data, named filename: String, completion: @escaping (URL? , Error?) -> Void) {
          
                  let reference = self.storageReference.child(filename)
                  let metadata = StorageMetadata()
                  metadata.contentType = "ourType" // in my example this was "PDF"
          
                  // we create an upload task using our reference and upload the 
                  // data using the metadata object
                  let uploadTask = reference.putData(data, metadata: metadata) { metadata, error in
          
                      // first we check if the error is nil
                      if let error = error {
          
                          completion(nil, error)
                          return
                      }
          
                      // then we check if the metadata and path exists
                      // if the error was nil, we expect the metadata and path to exist
                      // therefore if not, we return an error
                      guard let metadata = metadata, let path = metadata.path else {
                          completion(nil, NSError(domain: "core", code: 0, userInfo: [NSLocalizedDescriptionKey: "Unexpected error. Path is nil."]))
                          return
                      }
          
                      // now we get the download url using the path
                      // and the basic reference object (without child paths)
                      self.getDownloadURL(from: path, completion: completion)
                  }
          
                  // further we are able to use the uploadTask for example to 
                  // to get the progress
              }
          
              // MARK: - GET DOWNLOAD URL
              private func getDownloadURL(from path: String, completion: @escaping (URL?, Error?) -> Void) {
          
                  self.storageReference.child(path).downloadURL(completion: completion)
              }
          
          }
          

          【讨论】:

          • 感谢您的回答。要将其与@Sh_Khan 的答案联系起来,这表明应该在starsRef 上调用.downloadURL 而不是storageRef,如文档中所述,这对我来说更有意义
          • 当我尝试这种方法时,我收到了 Firebase 尚未配置的错误。我在 appDelegate 中有它并且工作正常,直到我添加了 init。有什么想法吗?
          【解决方案6】:

          你可以试试

          // Create a reference to the file you want to download
          let starsRef = storageRef.child("images/stars.jpg")
          
          // Fetch the download URL
          starsRef.downloadURL { url, error in
            if let error = error {
              // Handle any errors
            } else {
              // Get the download URL for 'images/stars.jpg'
            }
          }
          

          【讨论】:

          • 现在看来是唯一的解决方案了。虽然我不明白为什么不能从 StorageMetadata 实例访问 URL。
          • 文档说它将是storageRef.downloadURL而不是starsRef.downloadURL,但这对我来说没有任何意义,它应该是 starsRef .?
          • firebaser here 下载 URL 曾经包含在任务的元数据中,但这会影响性能,而并非所有用户都需要它。这就是为什么它现在总是需要单独调用,这样只有需要下载 URL 的用户才能看到这种性能影响。
          • @FrankvanPuffelen 谢谢,应该在 starsRefstorageRef 上调用它吗? starsRef 会更有意义,但文档却相反
          • @DavidSeek 的回答证实 .downloadURL 确实应该在 starsRef 上调用,而不是文档中所说的 storageRef,这对我来说更有意义
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-27
          • 1970-01-01
          • 2019-04-22
          相关资源
          最近更新 更多