The image.payload.read()
returns the raw data of the image and this is what we want, except we don't want to put it in the IMG tag's src attribute.
What we want, is to serve the raw image data as an image and put that image's URL to the src attribute.
Here is one example how it can be done with a temporary file.
And this is most likely the solution you want.
from tempfile import NamedTemporaryFile
from shutil import copyfileobj
tempFileObj = NamedTemporaryFile(mode='w+b',suffix='jpg')
copyfileobj(image.payload,tempFileObj)
tempFileObj.seek(0,0)
And then serve the file in a view
from flask import send_file
@app.route('/path')
def view_method():
response = send_file(tempFileObj, as_attachment=False, attachment_filename='myfile.jpg')
return response
It might be possible to send the image data straight from the ImageGridFSProxy object and skip the temporary file, but I am not sure about it.
----------
Now that you got your code done, I'll post the way I would have done it. And the way I tried to explain. :)
Here's my app.py.
from flask import Flask, send_file, render_template
import mongoengine as mo
app = Flask(__name__)
c = mo.connection.connect('localhost')
@app.route('/')
def index():
images = MyDoc.objects.all()
return render_template('template.html', images=images)
# Separate view for the images
@app.route('/image/<img_name>')
def image(img_name):
image = MyDoc.objects(file_name=img_name).first()
# This is where the tempfile stuff would have been if it would
# have been needed.
if image:
return send_file(image.payload, mimetype='image')
else:
return "404" # might want to return something real here too
class MyDoc(mo.Document):
file_name = mo.StringField(max_length=255, required=True)
payload = mo.ImageField(required=True)
if __name__ == "__main__":
app.run(debug=True)
And here's the template.
<html>
<body>
<div>
This is a body!
<div>
{% if images %}
{% for image in images %}
{{ image.file_name }}
<img src="/image/{{ image.file_name }}" />
I'm an image!<br><br>
{% endfor %}
{% endif %}
</div>
</div>
</body>
</html>
The whole tempfile
thing was unnecessary as the payload could be sent directly with the send_file
. The mimetype was needed to tell the browser that "this is an image" and the browser should just show it and not download it. It wasn't the as_attachment
as I suspected earlier.
This way there is no need to save the files with the tempfile
or into a directory where they would be served statically instead.