Я использую сервер разработки 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 (слишком много информации), но я ценю помощь.