Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve an image from google cloud storage using python flask

I'm currently working on a project running flask on the Appengine standard environment, and I'm attempting to serve an image that has been uploaded onto Google Cloud Storage on my project's default Appengine storage bucket.

This is the routing code I currently have:

# main.py

from google.appengine.api import images
from flask import Flask, send_file

app = Flask(__name__)

...

@app.route("/sample_route")
def sample_handler():
    myphoto = images.Image(filename="/gs/myappname.appspot.com/mysamplefolder/photo.jpg")
    return send_file(myphoto)
...

However, I am getting an AttributeError: 'Image' object has no attribute 'read' error.

The question is, how do I serve an image sourced from google cloud storage using an arbitrary route using python and flask?

EDIT:

I am actually trying to serve an image that I have uploaded to the default Cloud Storage Bucket in my app engine project.

I've also tried to serve the image using the following code without success:

# main.py

from google.appengine.api import images
from flask import Flask, send_file

app = Flask(__name__)

...

@app.route("/sample_route")
def sample_handler():
    import cloudstorage as gcs
    gcs_file = gcs.open("/mybucketname/mysamplefolder/photo.jpg")
    img = gcs_file.read()
    gcs_file.close()

    return send_file(img, mimetype='image/jpeg')
...
like image 282
B B Avatar asked Jan 26 '17 02:01

B B


2 Answers

I've used the GoogleAppEngineCloudStorageClient Python library and loaded images with code similar to the following example:

from google.appengine.api import app_identity
import cloudstorage
from flask import Flask, send_file
import io, os

app = Flask(__name__)

# ...

@app.route('/imagetest')
def test_image():

  # Use BUCKET_NAME or the project default bucket.
  BUCKET_NAME = '/' + os.environ.get('MY_BUCKET_NAME',
                                     app_identity.get_default_gcs_bucket_name())
  filename = 'mytestimage.jpg'
  file = os.path.join(BUCKET_NAME, filename)

  gcs_file = cloudstorage.open(file)
  contents = gcs_file.read()
  gcs_file.close()

  return send_file(io.BytesIO(contents),
                   mimetype='image/jpeg')
like image 156
BrettJ Avatar answered Oct 08 '22 18:10

BrettJ


Using google-cloud-storage==1.6.0

from flask import current_app as app, send_file, abort
from google.cloud import storage
import tempfile

@app.route('/blobproxy/<filename>', methods=['GET'])
def get(filename):
    if filename:
        client = storage.Client()
        bucket = client.get_bucket('yourbucketname')
        blob = bucket.blob(filename)
        with tempfile.NamedTemporaryFile() as temp:
            blob.download_to_filename(temp.name)
            return send_file(temp.name, attachment_filename=filename)
    else:
        abort(400)

I recommend looking at the docs for the path or string converters for your route, and NamedTemporaryFile defaults to delete=True so no residue. flask also figures out the mimetype if you give it a file name, as is the case here.

like image 25
opyate Avatar answered Oct 08 '22 17:10

opyate