#python #html #google-app-engine #flask #google-cloud-storage
# #python #HTML #google-app-engine #flask #google-облачное хранилище
Вопрос:
Я пытаюсь создать веб-сайт, который принимает ввод текста, генерирует изображение, а затем отображает это изображение обратно в html.
Это отлично работает, записывая изображение в статический каталог, когда у меня есть локальная тестовая реализация, но когда я нажимаю на Google Cloud, мне не разрешается записывать в каталог. Я выяснил, как сохранить изображение в моем хранилище Google Cloud, но теперь я не могу вернуть изображение для отображения в шаблоне html.
Я использую Flask и python 3.7
Вот что я делаю:
from flask import Flask, render_template, request, send_file
import time
#import cloudstorage
import io, os
from google.cloud import storage
import tempfile
import functions
app = Flask(__name__)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
@app.route("/")
def home():
return render_template("home_css.html")
@app.route('/', methods=['POST'])
def my_form_post():
text = request.form['text']
URL = functions.main(text)
print(URL)
return render_template("return_img_css.html", picture_path = URL, screen_name = text)
Где часть функций содержит блок, который УСПЕШНО СОХРАНЯЕТ изображение для возврата URL-адреса изображения:
def make_plot():
....
# NEED to SAVE THE IMAGE TO GOOGLE CLOUD
client = storage.Client(project='meytweets')
bucket = client.bucket('meytweets.appspot.com')
savename = 'static/' screen_name '_network.png'
blob = bucket.blob(savename)
# temporarily save image to buffer
buf = io.BytesIO()
plt.savefig(buf, format='png')
# upload buffer contents to gcs
blob.upload_from_string(
buf.getvalue(),
content_type='image/png')
buf.close()
return blob.public_url
Где этот URL-адрес обычно выглядит так:
https://storage.googleapis.com/meytweets.appspot.com/static/twitter_network.png
И шаблон HTML выглядит так:
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %} Network for Twitter User: {{ screen_name }} {% endblock %}</h1>
<img src="{{ picture_path }}" >
{% endblock %}
Вот app.yaml:
runtime: python37
env_variables:
CLOUD_STORAGE_BUCKET: meytweets.appspot.com
handlers:
- url: /static
static_dir: public
- url: /.*
script: auto
Как я писал выше, изображение сохраняется в моем облачном хранилище Google, но затем я не могу вернуть его для отображения в html:
скриншот
Я открыт для других стратегий, которые не записываются в Google Cloud, все, что работает для отображения изображения, которое я создаю в matplotlib, меня устраивает.
Ответ №1:
При запуске приложения в бессерверной среде /tmp
доступен для записи только каталог. Вы не можете изменить содержимое другого каталога, например /static
. Кроме того, /tmp
каталог представляет собой файловую систему в памяти, и, таким образом, когда экземпляр уничтожается, все /tmp
они исчезают.
Теперь вы можете попробовать установить /tmp
в обработчиках. Я никогда не тестировал, не уверен в результате и его согласованности.
Другое решение — сохранить изображение в облачном хранилище Google и, наконец, сгенерировать ваш HTML с изображением в облачном хранилище Google, разумеется, общедоступном.
Комментарии:
1. похоже, вы предлагаете мне попытаться сохранить изображение в / tmp вместо этого, а затем отправить изображение из temp в HTML? У меня создалось впечатление, что я могу обслуживать только из «статического», но я могу использовать свое хранилище Google Cloud Storage как статическое, используя обработчик: « обработчики: — url: / static static_dir: public
2. Должно работать обслуживание из / tmp в HTML (я никогда не пробовал, но по замыслу это не должно работать). Решение для облачного хранилища лучше, но вам нужно сделать ваше хранилище общедоступным, чтобы позволить любому получить к нему доступ.
Ответ №2:
Прошло некоторое время с тех пор, как был задан этот вопрос, но мне нужно было сделать то же самое, и он заработал. Я сохраняю изображения в хранилище объектов Google и вставляю их в шаблоны jinja2 в виде данных в кодировке base64 в тегах img.
Маршрут:
@app.route("/view/<string:blob_name>")
def view(blob_name):
bucket = get_bucket()
blob = bucket.get_blob(blob_name)
content = blob.download_as_bytes()
image = base64.b64encode(content).decode("utf-8")
return render_template('view.html', content_type=blob.content_type, image=image)
Шаблон:
<body>
<h1>Image:</h1>
<img src="data:{{ content_type }};base64,{{ image }}" />
</body>
Это решение работает, если flask работает в бессерверной среде, где вы не можете создавать временные файлы и не хотите делать данные общедоступными.