Kency
Kency

Reputation: 660

Firebase Database Rule - Get Image Access Denied (iOS)

Firebase is very new with me. I watched a tutorial on Youtube to build an app with Firebase. Unfortunately, I got an error when I try to access the URL of the Image from Firebase, I can't figure out why I got an error until I print out the URL to console and copy-pasted it to address bar on a browser.

I got code 403 - Access denied from Firebase. I also tried using Google to solve my problem, but nothing changed. I re-wrote my database rule, but it doesn't work. Please help me.

My code

extension UIImageView
{
    func skin() {
        self.layer.cornerRadius = 20
        self.clipsToBounds = true
    }


    func loadAvatar(link:String){
        let queue:DispatchQueue = DispatchQueue(label: "LoadingImage", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, target: nil)
        let activity:UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.whiteLarge)

        activity.frame = CGRect(x: self.frame.size.width/2, y: self.frame.size.height/2, width: 0, height: 0)

        activity.color = UIColor.blue
        self.addSubview(activity)
        activity.startAnimating()
        queue.async {
            let url:URL = URL(fileURLWithPath: link)
            do{
                let data:Data =  try Data(contentsOf: url)
                DispatchQueue.main.async(execute: {
                    activity.stopAnimating()
                    self.image = UIImage(data: data)
                })

            }catch{// my app always jump into catch because can access image
                activity.stopAnimating()
                print("Error ")//error 
            }
        }
    }
}

Place I called Loadavatar function:

extension ScreenListFriendViewController : UITableViewDataSource, UITableViewDelegate {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return listFriend.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ScreenListFriendTableViewCell

        cell.lblName.text = listFriend[indexPath.row].fullname
        cell.imgAvatar.loadAvatar(link: listFriend[indexPath.row].linkAvt)
        return cell
    }

}

My Firebase database rule:

{
  "rules": {
    ".read": true,
    ".write":true
  }
}

My image URL looks like this:

https:/firebasestorage.googleapis.com/v0/b/appchat-e1cc4.appspot.com/o/images%[email protected]%3Falt=media&token=275419bf-c0a4-4fc5-932e-624df797f9d3

Note: https:/, I don't know why I only got 1 /.

PS: I use Xcode 8 and Swift 3

Upvotes: 1

Views: 446

Answers (2)

sphippen
sphippen

Reputation: 404

In the loadAvatar function, you pass the download URL as a String to init(fileURLWithPath: String):

queue.async {
  let url:URL = URL(fileURLWithPath: link)
  do {

You should pass the download URL to init?(string: String) instead. Alternatively, just use the URL our library returns, instead of converting it to String and back to URL.

Your actual image link is

https://firebasestorage.googleapis.com/v0/b/appchat-e1cc4.appspot.com/o/images%[email protected]?alt=media&token=275419bf-c0a4-4fc5-932e-624df797f9d3

The init(fileURLWithPath: String) method interprets the string as a local file path, which isn't what you want. It also explains why the slashes after https got collapsed and the % and ? characters got URL-encoded.

Upvotes: 1

Andrew Veresov
Andrew Veresov

Reputation: 319

Seems it's a rules try to setup rules similar to this:

{
  "rules": {
    "my_field": {
    ".read": "auth == null",
    ".write": "auth == null"
    }
  }
}

Upvotes: 0

Related Questions