简体   繁体   中英

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')
...

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')

Are you trying to accomplish something like this:

@app.route("/sample_route")
def sample_handler():
    import urllib2
    import StringIO

    request = urllib2.Request("{image url}")

    img = StringIO.StringIO(urllib2.urlopen(request).read())
    return send_file(img, mimetype='image/jpeg') # display in browser

or

    return send_file(img) # download file

The image url is needed, not a relative path. You could just do a redirect to the image url, but they would get a 301.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM