Squeak.ru - шаблоны программирования

Проблемы с отображением изображения из облачного хранилища в Google App Engine, Python

Я использую сервер разработки python 1.9.20 для App Engine на Mac.

Я добился успеха с Blobstore, но я переключаю свой код на использование облачного хранилища перед запуском своего сайта.

Я не получаю ошибок в консоли. Но у меня не отображается изображение в браузере. В браузере отображается значок «изображение не найдено». ("?" в Safari.)

Я собрал свой код облачного хранилища из примеров, упомянутых здесь, на SO. В основном из кода voscausa (см. Ниже).
URL-адрес для обслуживания выглядит правильным (исходя из того, что я ожидал от образца документации).

Но изображения нет. Если вы понимаете, что я делаю не так, я был бы рад услышать ваш отзыв.

Я сохраняю ключ и URL-адрес загруженного большого двоичного объекта изображения в объект UserProfile.

class UserProfile(ndb.Model):
    profile_image_url = ndb.StringProperty(indexed=False, default=None)
    profile_image_key = ndb.BlobKeyProperty(indexed=False, default=None)

Я пишу в GCS и генерирую здесь ключ хранилища больших двоичных объектов:

def CreateFile(filename, upload_file, content_type):
    with gcs.open(filename, 'w',
                  options={b'x-goog-acl': b'public-read'},
                  content_type=content_type) as f:
        f.write(upload_file)
    blobstore_filename = '/gs' + filename
    return blobstore.create_gs_key(blobstore_filename)

Мой обработчик загрузки выглядит так:

class UploadHandler(webapp2.RequestHandler):    
    def post(self):
        user = users.get_current_user()
        path = self.request.path
        item = self.request.get('item')
        image_num = self.request.get('image')
        src = self.request.get('src')
        group_id = self.request.get('id')

        if user:
            this_user_qry = UserProfile.query(UserProfile.user_id == user.user_id(), ancestor=user_key(user.user_id()))
            try:
                this_user = this_user_qry.get()
            except:
                logging.error('In UploadHandler, src = profile this_user_qry.get() failed')

        if src == 'profile':
            return_path = '/edit_profile#image'

            #if this_user.profile_image_key != None:

                #''' profile image exists, removing the current image, replaced with this_user.profile_image_key '''
                #blobstore.delete(this_user.profile_image_key)

                #this_user.profile_image_key = None
                #this_user.profile_image_url = None

            bucket_name = os.environ.get('BUCKET_NAME',
                                         app_identity.get_default_gcs_bucket_name())

            file_data = self.request.get("file", default_value=None)
            file_name = self.request.POST["file"].filename
            file_ext = file_name.lower().split('.')[-1]
            gcs_file = "/%s/profile/%s/%s" % (bucket_name, str(user.user_id()), file_name)
            #gcs_file = "/%s/%s" % (bucket_name, file_name)

            mimetypes.init()
            content_type = mimetypes.guess_type(file_name)[0]

            if file_data:
                blob_key = blobstore.BlobKey(CreateFile(gcs_file, file_data, content_type))

                if file_ext in ['png', 'jpg', 'gif']:
                    serving_url = images.get_serving_url(
                        blobstore.create_gs_key('/gs' + gcs_file), secure_url=True)
                elif gae_development:
                    # this SDK feature has not been documented yet !!!
                    serving_url = 'http://localhost:8080/_ah/gcs' + gcs_file
                else:
                    serving_url = 'https://storage.googleapis.com' + gcs_file
                print "\n-new-\nserving_url = %s" % serving_url

                this_user.profile_image_key = blob_key
                this_user.profile_image_url = serving_url
                try:
                    this_user.put()
                except:
                    logging.exception('In UploadHandler, if blob_key, this_user.put()')
                    self.redirect('/upload_image_error')
                else:
                    self.redirect('/edit_profile#image')

Печатные значения для [gcs_file, blob_key, serve_url]:

gcs_file = /app_default_bucket/profile/112118202356943244222/MichaelEdland_112514.jpg

blob_key = encoded_gs_file: YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmR0LTE

serv_url = http://0.0.0.0:8080/_ah/img/encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==

Для шаблона Jinja:

Я передаю это значение в шаблон:

'profile_image_url': this_user.profile_image_url,

А это для отображения изображения на странице профиля:

<img border="0" src="{{ profile_image_url | safe }}" width="100%" >

В консоли App Engine Console Datastore Viewer

Entity Kind Blobinfo содержит две записи для этого изображения.

Ключевые названия

1) 3kD4IorO9hfg-J7OrZtmVQ==

2) encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==

имена файлов 1) MichaelEdland_112514.jpg 2) None

размеры

1) 166464 2) 250

Есть одна запись для BlobServingUrl

key name и blob_key оба:

encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==

GSFileInfo, имя ключа = encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==

content_type = image/jpeg filename = /app_default_bucket/profile/112118202356943244222/MichaelEdland_112514.jpg

Некоторые вещи, которые я нашел полезными (чтобы добраться до этой точки):

Ответ voscausa был полезен Как обслуживать файлы облачного хранилища с помощью SDK движка приложений < / а>

и его измененный пример кода был полезен https://github.com/voscausa/appengine-gcs-blobstore-python

в документации есть пример того, как выглядит обслуживающий URL

Я также прочитал документы Google, которые меня зашли так далеко. (Не могу размещать ссылки из-за отсутствия репутации)

Но теперь я, кажется, застрял.

Заранее спасибо. После года ежедневного использования StackOverflow я наконец-то должен задать вопрос. :-) Вероятно, 511 (слишком много информации), но я ценю помощь.


Ответы:


1

Можете ли вы "получить" файл изображения, чтобы увидеть, правильно ли он был передан? То есть проверить, было ли оно передано как текстовое или как двоичное?

Этот вопрос может быть полезным: Как записать необработанные байты в облачное хранилище Google с помощью Python API от GAE

Особенно эта цитата из принятого ответа:

Я полагаю, проблема в том, что метод gcs_file.write () ожидает данные типа "str".

В вашей функции CreateFile оператор f.write (upload_file) может неправильно записывать файл upload_file.

04.06.2015
  • Спасибо, Ирв. Я не получаю сообщения об ошибке. Я попробовал wget, как вы предложили: wget serve_url: Это дает файл с информацией о загруженном файле. [Content-Type, Content-Length, Content-MD5 и т. Д.] Вероятно, поэтому изображение не отображается. Я ожидал, что URL-адрес обслуживания будет… ну, URL-адресом, который я мог бы использовать для обслуживания изображения. 04.06.2015
  • В документации для Google Blobstore Python API есть пример UploadHandler, который вы можете изменить для своего приложения: [ссылка] cloud.google.com/appengine/docs/python/blobstore/ 22.06.2015
  • да. Спасибо. Я видел это. Думаю, это был первый результат поиска. Я не ленивый. Просто у меня были проблемы с осмыслением нового рабочего процесса. Думаю, теперь у меня есть решение. Я это проверяю. Когда у меня будет время, я отправлю его. 23.06.2015
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...