如何在 aiohttp 中发回图像/文件



我需要知道如何在aiohttp中发送回图像。我编写了一个用于调整图像大小的服务器。我使用了aiohttp.web.FileResponse,但它需要保存文件,而且有点问题(很多文件需要保存在硬盘上(。

有没有办法灵活地做到这一点(不保存文件(?也许是从图像字节或其他什么?我阅读了 aiohttp 文档,但它没有做太多事情。

这是我试图做的:

  1. 文件响应

在这里,我必须保存它才能发回响应

image = tasks.get(key)  # PIL.Image
image.save('im_server/pil_{}.jpg'.format(key))  
resp = web.FileResponse(f'im_server/pil_{key}.jpg')
return resp
  1. StreamResponse

当我使用此代码发出请求时,我已经取回了文件(它正在上传到我的计算机上(,但它不是图像。如果我尝试将其作为图像打开,它说文件已损坏,无法打开:(

image = tasks.get(key)  # PIL.Image
resp = web.StreamResponse(status=200)
resp.headers['Content-Type'] = 'Image/JPG'
await resp.prepare(request)
await resp.write(image.tobytes())
return resp

您可以使用tempfile.SpooledTemporaryFile来完成保存工作。它旨在将临时文件存储在内存中,并且仅在文件大小超过max_size参数时将文件保存在磁盘上。请注意,此参数默认为 0,因此您需要将其更改为合适的大小以避免将所有内容存储在磁盘上。用法非常简单,SpooledTemporaryFile将返回一个file_like对象句柄,您可以像写入常规文件一样写入该句柄。一旦你不需要它,只需关闭它,它就会自动从内存或磁盘中删除。您可以参考该文档以查看更多用法:https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile。

您可以使用io.BytesIO.

async def img_resize(req: web.Request):
data = await req.post()
url = data.get('url')
width = data.get('width')
height = data.get('height')
if not all((url, width, height)):
return web.HTTPNotFound()
try:
width = int(width)
height = int(height)
except ValueError:
return web.HTTPError()
async with ClientSession() as session:
async with await session.get(url) as res:
if res.status != 200:
return web.HTTPNotFound()
img_raw = await res.read()
im = Image.open(BytesIO(img_raw))
im = im.resize((width, height), Image.BICUBIC)
stream = BytesIO()
im.save(stream, "JPEG")
return web.Response(body=stream.getvalue(), content_type='image/jpeg')

最新更新