【问题标题】:Trouble displaying image from cloud storage on Google App Engine, Python无法在 Google App Engine、Python 上显示来自云存储的图像
【发布时间】:2015-08-12 23:32:05
【问题描述】:

我在 Mac 上使用 App Engine python 开发服务器 1.9.20。

我在 Blobstore 上取得了成功,但在启动我的网站之前,我将我的代码切换为使用 cloudstore。

我在控制台中没有收到任何错误。但我没有在浏览器中显示图像。浏览器显示“找不到图像图标”。 (“?”在 Safari 中。)

我根据 SO 上引用的示例拼凑了我的云存储代码。 主要来自 voscausa 的代码(参考如下)。
服务 url 看起来是正确的(基于我对示例文档的期望)。

但没有图像。如果您知道我做错了什么,我很高兴听到您的意见。

我正在将上传的图像 blob 密钥和 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 并在此处生成 blobstore 密钥:

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, serving_url] 的打印值为:

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

blob_key = encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==

serving_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 控制台中数据存储查看器

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 文件名 = /app_default_bucket/profile/112118202356943244222/MichaelEdland_112514.jpg

我发现一些有用的东西(为了达到这一点):

voscausa 的回答很有帮助 How to serve cloudstorage files using app engine SDK

他修改后的代码示例很有帮助 https://github.com/voscausa/appengine-gcs-blobstore-python

在文档中有一个服务网址的示例

我确实也阅读了谷歌文档,这让我走到了这一步。 (由于缺乏声誉,我无法发布链接)

但现在我似乎被卡住了。

提前致谢。 每天都在用 StackOverflow 一年,终于要问一个问题了。 :-) 可能是 511(信息太多),但我感谢您的帮助。

【问题讨论】:

    标签: python image google-app-engine google-cloud-storage


    【解决方案1】:

    您能否“wget”图像文件以查看它是否正确传输?即,检查它是以文本还是二进制形式传输的?

    这个问题可能会有所帮助: How to write raw bytes to Google cloud storage with GAE's Python API

    特别是来自已接受答案的引用:

    我想问题是 gcs_file.write() 方法需要“str”类型的数据。

    在您的 CreateFile 函数中,f.write(upload_file) 语句可能会错误地写入 upload_file。

    【讨论】:

    • 谢谢欧文。我没有收到错误消息。我按照您的建议尝试了 wget: wget serving_url: 这会产生一个文件,其中包含有关上传文件的信息。 [Content-Type、Content-Length、Content-MD5 等...] 这可能是图像不显示的原因。我期待服务网址是……嗯,我可以用来提供图片的网址。
    • Google Blobstore Python API 的文档有一个 UploadHandler 示例,您可以为您的应用程序修改它:[link]cloud.google.com/appengine/docs/python/blobstore/…
    • 是的。谢谢。我确实看到了。我认为这是第一个搜索结果。我并不懒惰。我只是在摸索新的工作流程时遇到了麻烦。我想我现在有一个解决方案。我正在测试它。当我有时间时,我会发布它。
    猜你喜欢
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    • 2014-09-28
    • 2015-05-15
    • 2016-09-28
    相关资源
    最近更新 更多