无法保存对 BytesIO 缓冲区的更改
Can't save changes to BytesIO buffer
在学习 Flask 的同时,我编写了一个小型服务来接收图像、调整大小并降低图像质量。
为了避免写入磁盘然后删除它,我使用了一个缓冲区,它工作得很好。但是现在我无法使用 flask send_file 发送它。我尝试了一些解决方案,包括使用 werkzeug FileWrapper 包装它并使用 Response 发送,但它也没有用。此外,它没有显示任何类型的错误...
@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)
当我指向一个存在于我的系统中的文件时,它工作正常...
更新
有人指出我没有使用buffer.seek(0)
,装上后,我开始收到请求中的图像,但图像与我的预期相差甚远。
例如,我的测试图像是 5.2MB,当我将它保存到磁盘而不是缓冲区时,它变为 250KB,但是当我尝试将它保存到缓冲区并使用 [=40 发送它时=], 它变成了 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)
我正在编辑这个问题标题并删除 flask 的标签,因为我的问题似乎只是缺乏关于 io 的 BytesIO 库的知识。
更新 2
当我想到它时,我正在做另一个项目。如果我创建一个新的缓冲区来保存已经修改过的图像怎么办?
它奏效了。
@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)
所以,显然我无法替换 BytesIO 缓冲区的内容?任何人都知道我做错了什么? (是的,我成功了,但我想其他人也会从同样的问题中受益?)
在我的机器上测试,truncate()
在 save(...)
之后工作正常。
import math
import shutil
from PIL import Image
from io import BytesIO
src = r"C:\Users\justin\Desktop\test.jpg"
f = open(src, 'rb')
buffer = BytesIO()
shutil.copyfileobj(f, buffer)
print(f.tell(), buffer.tell())
f.close()
buffer.seek(0)
image = Image.open(buffer)
image.show()
print(buffer.tell())
print(image.size)
w, h = image.size
w, h = math.floor(w*0.75), math.floor(h*0.75)
print(w, h)
smaller = image.resize((w, h), Image.ANTIALIAS)
smaller.show()
print(smaller.size)
buffer.seek(0)
smaller.save(buffer, format='JPEG', optimize=True)
print(buffer.tell())
buffer.truncate()
buffer.seek(0)
out = Image.open(buffer)
out.show()
print(out.size)
在学习 Flask 的同时,我编写了一个小型服务来接收图像、调整大小并降低图像质量。
为了避免写入磁盘然后删除它,我使用了一个缓冲区,它工作得很好。但是现在我无法使用 flask send_file 发送它。我尝试了一些解决方案,包括使用 werkzeug FileWrapper 包装它并使用 Response 发送,但它也没有用。此外,它没有显示任何类型的错误...
@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)
当我指向一个存在于我的系统中的文件时,它工作正常...
更新
有人指出我没有使用buffer.seek(0)
,装上后,我开始收到请求中的图像,但图像与我的预期相差甚远。
例如,我的测试图像是 5.2MB,当我将它保存到磁盘而不是缓冲区时,它变为 250KB,但是当我尝试将它保存到缓冲区并使用 [=40 发送它时=], 它变成了 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)
我正在编辑这个问题标题并删除 flask 的标签,因为我的问题似乎只是缺乏关于 io 的 BytesIO 库的知识。
更新 2
当我想到它时,我正在做另一个项目。如果我创建一个新的缓冲区来保存已经修改过的图像怎么办?
它奏效了。
@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)
所以,显然我无法替换 BytesIO 缓冲区的内容?任何人都知道我做错了什么? (是的,我成功了,但我想其他人也会从同样的问题中受益?)
在我的机器上测试,truncate()
在 save(...)
之后工作正常。
import math
import shutil
from PIL import Image
from io import BytesIO
src = r"C:\Users\justin\Desktop\test.jpg"
f = open(src, 'rb')
buffer = BytesIO()
shutil.copyfileobj(f, buffer)
print(f.tell(), buffer.tell())
f.close()
buffer.seek(0)
image = Image.open(buffer)
image.show()
print(buffer.tell())
print(image.size)
w, h = image.size
w, h = math.floor(w*0.75), math.floor(h*0.75)
print(w, h)
smaller = image.resize((w, h), Image.ANTIALIAS)
smaller.show()
print(smaller.size)
buffer.seek(0)
smaller.save(buffer, format='JPEG', optimize=True)
print(buffer.tell())
buffer.truncate()
buffer.seek(0)
out = Image.open(buffer)
out.show()
print(out.size)