Как мне загружать / загружать фотографии в хранилище Google (Firebase)?

#firebase #flask #firebase-storage #pyrebase

# #firebase #flask #firebase-хранилище #pyrebase

Вопрос:

По сути, моя проблема заключается в том, что я, по-видимому, не могу даже приблизиться к загрузке фотографий в мой проект Firebase. Я могу передавать информацию о пользователях в базу данных в реальном времени, а также успешно интегрировал аутентификацию Firebase, которую я использую с сеансами Flask для сохранения входа пользователей в систему. Похоже, что для сохранения файлов / фотографий вам нужно использовать хранилище Firebase, но я не могу понять, как это сделать.

Пользователи могут нажать и кнопку «загрузить файл» в моем маршруте «/ upload-image», и прямо сейчас я сохраняю изображение (после того, как пользователь загрузит его) в папку в том же каталоге, что и мой fiddl.py досье.

Весь следующий код находится в моем Fiddl.py файле.

Вот мои инициализации Firebase:
Обратите внимание, storageRef это то, что я пробовал, но такого, как ref() в хранилище, нет, поэтому я получаю ошибки. Также у меня есть storage , потому что я считаю, что это ссылается на хранилище моих проектов.

 #initialize database
firebase = pyrebase.initialize_app(json.load(open('firebase/firebaseConfig.json')))
auth = firebase.auth()
db = firebase.database()                                    
#storageRef = firebase.storage.ref()                           #Points to the root reference
app.secret_key = os.urandom(24)                                #secret key:track if user is logged in
storage = firebase.storage("gs://fiddl-dev.appspot.com")      
 

Вот конфигурации, которые я использовал для хранения загруженного пользователями изображения в локальной папке /FIDDL/Photo test . Я сократил название пути для вашего удобства. Примечание: я надеюсь позже добавить эти конфигурации в их собственный файл для обеспечения безопасности, все еще не уверенный на 100%, как они должны работать. Наряду с этим у меня есть маршрут, по которому пользователь загружает фотографию со своего устройства.

 #temp image upload location
#TODO: put these in a private config file
app.config["IMAGE_UPLOAD"] = "/FIDDL//photosTest"
app.config["ALLOWED_IMAGE_EXTENSIONS"] = ["PNG", "JPG", "JPEG"]
app.config["MAX_IMAGE_FILESIZE"] = 1.5 * 1024 * 1024    #1,572,864 Bytes or 1572.864 KB

# Upload Image
@app.route('/upload-image', methods=["GET", "POST"])
def upload_image():
    try:
        print(session['usr'])                   #this is equal to logged in users id token->  user['idToken']
        app.logger.info("A user is already logged in")
        #TODO: add a logout button, make sure to delete session for use on logout

        # Alert Messages
        noFileName = 'Image must have a file name.'
        badFileSize = 'Image file size is too large.'
        badFileName = 'That image extension or file name is not allowed'
        dataAdded = 'User photos added to realtime database'

        if request.method == "POST":
            if request.files:
                image = request.files["image"]                          #works the same as user input emal in register, get the image file
                print(image)

                #Grab the file size
                image.seek(0, os.SEEK_END)
                file_size = image.tell()
                app.logger.info("Image File Size: ")
                app.logger.info(file_size)

                #Check the image file size
                if not allowed_image_filesize(file_size):
                    #TODO: alert user on screen of the issue
                    app.logger.info(badFileSize)
                    return redirect(request.url)
                
                #Check for file name
                if image.filename == "":
                    app.logger.info(noFileName)
                    return redirect(request.url)
                
                #Check if image has correct type
                if not allow_image(image.filename):
                    app.logger.info(badFileName)
                    return redirect(request.url)
                else:
                    filename = secure_filename(image.filename)          #create new secure file name
                    app.logger.info(filename)
                    print(auth.current_user)
                    #Add data to realtime database
                    #TODO: figure out how to store photos in firebase
                    
                 

                    #Update progress
                    app.logger.info(dataAdded)




                    #image.save(os.path.join(app.config["IMAGE_UPLOAD"], filename))  #save images to /photosTest for testing
                    #print("image saved")
                
                return redirect(request.url)
    except KeyError:
        app.logger.info("No user logged in, redirect to login")
        return redirect(url_for('login'))
    
    return render_template("upload_image.html")
 

Вот правила для Firebase /Development /Storage /Rules. Я использую аутентификацию Firebase, но все еще получаю сообщение об ошибке:

     "code": 403,
    "message": "Permission denied. Could not perform this operation"
  }
 

Правила:

 rules_version = '2';

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/fiddl-dev.appspot.com/o {
    // Files look like: "user/<UID>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
        allow write: if request.auth != null;
      allow read: if true; 
    }
  }
}
 

Я знаю, что на самом деле здесь нет проблемы, которую нужно исправить, но любая точка в правильном направлении была бы супер! Спасибо!

Комментарии:

1. Как упоминалось здесь , просто сделайте что-то вроде firebase.storage().child("images/example.jpg").put("example2.jpg") — вы пробовали этот код?

2. Я считаю, что это работает, поскольку правила для моего хранилища запрещают мне put использовать «error»: { «code»: 403, «message»: «Отказано в разрешении. Не удалось выполнить эту операцию » }

3. Хм, вы уже настроили хранилище Firebase в своем проекте Firebase? Кроме того, возможно, проверьте, что ваши правила позволят вашему серверу добавлять файлы

4. Хорошо, ваше исправление сработало! Огромное спасибо @BlunderingPhilosopher! Теперь, чтобы отредактировать мои правила и выяснить, как правильно разрешать фотографии только аутентифицированным пользователям put . Я думаю, мне может понадобиться использовать Firebase Admin.

5. Спасибо за всю вашу помощь @BlunderingPhilosopher! Я обязательно прочитаю это и внесу свои новые рабочие правки в свой исходный пост, поскольку было еще несколько исправлений, которые мне нужно было внести, чтобы все заработало! Лучшие.

Ответ №1:

Ответ TLDR, включая некоторые небольшие проверки файлов, является одной из причин, по которой у меня возникла проблема. Гораздо больше деталей выше, если необходимо.

Чтобы загрузить изображение / файл в хранилище Google Firebase:

 firebase = pyrebase.initialize_app(json.load(open('firebase/firebaseConfig.json')))
storage = firebase.storage("gs://fiddl-dev.appspot.com")

app.config["IMAGE_UPLOAD"] = "/FIDDL//photosTest"
app.config["ALLOWED_IMAGE_EXTENSIONS"] = ["PNG", "JPG", "JPEG"]
app.config["MAX_IMAGE_FILESIZE"] = 1.5 * 1024 * 1024    #1,572,864 Bytes or 1572.864 KB

# Upload Image
@app.route('/upload-image', methods=["GET", "POST"])
def upload_image():
    try:
       if request.method == "POST":
            if request.files:
                image = request.files["image"]                          

                #Grab the file size
                image.seek(0, os.SEEK_END) # Using seek here requires another later
                file_size = image.tell()

                #Check the image file size
                if not allowed_image_filesize(file_size):
                    return redirect(request.url)
                
                #Check for file name
                if image.filename == "":
                    return redirect(request.url)
                
                #Check if image has correct type
                if not allow_image(image.filename):
                    return redirect(request.url)
                else:

                    filename = secure_filename(image.filename)  #create new secure file name        
                    image.seek(0)
                    storage.child("images/"   filename).put(image)
     except: 
          ...