PIL.Image.open()
takes as fp
argumnet the following:
fp
– A filename
(string), pathlib.Path
object or a file
object. The
file object must implement file.read()
, file.seek()
, and
file.tell()
methods, and be opened in binary mode.
Using a BytesIO
stream, you would need to have something like the below (as shown in client side of this answer):
Image.open(io.BytesIO(file.file.read()))
However, you don't really have to use an in-memory bytes buffer, as you can get the actual file object using the .file
attribute of UploadFile
. As per the documentation:
file
: A SpooledTemporaryFile
(a file-like
object).
This is the actual Python file that you can pass directly to other
functions or libraries that expect a "file-like" object.
Example - Saving image to disk:
# ...
from fastapi import HTTPException
from PIL import Image
@app.post("/upload")
def upload(file: UploadFile = File()):
try:
im = Image.open(file.file)
if im.mode in ("RGBA", "P"):
im = im.convert("RGB")
im.save('out.jpg', 'JPEG', quality=50)
except Exception:
raise HTTPException(status_code=500, detail='Something went wrong')
finally:
file.file.close()
im.close()
Example - Saving image to an in-memory bytes buffer (see this answer):
# ...
from fastapi import HTTPException
from PIL import Image
@app.post("/upload")
def upload(file: UploadFile = File()):
try:
im = Image.open(file.file)
if im.mode in ("RGBA", "P"):
im = im.convert("RGB")
buf = io.BytesIO()
im.save(buf, 'JPEG', quality=50)
# to get the entire bytes of the buffer use:
contents = buf.getvalue()
# or, to read from `buf` (which is a file-like object), call this first:
buf.seek(0) # to rewind the cursor to the start of the buffer
except Exception:
raise HTTPException(status_code=500, detail='Something went wrong')
finally:
file.file.close()
buf.close()
im.close()
For more details and code examples on how to upload files/images using FastAPI, please have a look at this answer and this answer. Also, please have a look at this answer for more information on defining your endpoint with def
or async def
.