While I am learning Flask, I wrote a small service that receives a image, resize and reduce it's quality.
To avoid write it to the disk and then delete it, I use a buffer, and it worked fine. But now I can't send it using flask send_file. I tried a few solutions that include wrap it using werkzeug FileWrapper and send using Response, but it also did not work. Also, it does't show any kind of error...
@app.route('/api/convert', methods=['POST'])
def convert():
if 'image' not in request.files:
return 'No image!'
if request.files['image'].content_type not in ALLOWED_CONTENT:
return 'Not an allowed image!'
filename = request.files['image'].filename
mimetype = request.files['image'].mimetype
print(mimetype)
buffer = io.BytesIO()
request.files['image'].save(buffer)
image = Image.open(buffer)
w, h = resize_image(*image.size)
image = image.resize((w, h), Image.ANTIALIAS)
print(type(buffer))
image.save(buffer,
format=mimetype.split('/')[-1],
optimize=True,
quality=DEFAULT_QUALITY)
return send_file(buffer,
mimetype=mimetype,
attachment_filename=filename,
as_attachment=True)
When I point to a file that exist in my system, it works fine...
UPDATE
It was pointed out that I was not using buffer.seek(0)
, after doing putting it on, i started to receive the image in my requests, but the image is far from what I expected.
For example, my test image is 5.2MB, when I save it to the disk instead of the buffer, it goes to 250KB, but when i try to save it to the buffer, and send it using send_file, it goes to 5.5MB...
@app.route('/api/convert', methods=['POST'])
def convert():
if 'image' not in request.files:
return 'No image!'
if request.files['image'].content_type not in ALLOWED_CONTENT:
return 'Not an allowed image!'
filename = request.files['image'].filename
mimetype = request.files['image'].mimetype
buffer = io.BytesIO()
request.files['image'].save(buffer)
image = Image.open(buffer)
w, h = resize_image(*image.size)
buffer.seek(0)
image = image.resize((w, h), Image.ANTIALIAS)
image.save(buffer,
format=mimetype.split('/')[-1],
optimize=True,
quality=DEFAULT_QUALITY)
buffer.seek(0)
return send_file(buffer,
mimetype=mimetype,
attachment_filename=filename,
as_attachment=True)
I am editing this question title and removing the tags for flask because it seems that my problem is just the lack of knowledge about io's BytesIO library.
UPDATE 2
I was working in another project when it came to my mind. What if I create a new buffer to save the image already modified?
And it worked.
@app.route('/api/convert', methods=['POST'])
def convert():
if 'image' not in request.files:
return 'No image!'
if request.files['image'].content_type not in ALLOWED_CONTENT:
return 'Not an allowed image!'
filename = request.files['image'].filename
mimetype = request.files['image'].mimetype
buffer = io.BytesIO()
buffer_final = io.BytesIO()
request.files['image'].save(buffer)
image = Image.open(buffer)
w, h = resize_image(*image.size)
image = image.resize((w, h), Image.ANTIALIAS)
image.save(buffer_final,
format=mimetype.split('/')[-1],
optimize=True,
quality=75)
buffer_final.seek(0)
return send_file(buffer_final,
mimetype=mimetype,
attachment_filename=filename,
as_attachment=True)
So, apparently I can't replace the content of the BytesIO buffer? Anyone knows what I am doing wrong? (yeah, I made it work, but I guess that other people would benefit from the same problem?)
Tested on my machine and
truncate()
aftersave(...)
works just fine.