I am using a POST
request for uploading a file to a FastAPI application through Postman, and save it to my local directory. However, a 422 (Unprocessable entity)
error is raised, saying that the file
is missing. I selected the binary
option to upload the file, as can be seen in the image below:
Below is how my FastAPI backend looks like:
main.py
from fastapi import FastAPI
from api.endpoints.vendor import router
app = FastAPI(title='Vendor Acknolegment API')
app.include_router(router, prefix='/vendor', tags=['vendor confirmation'])
if __name__ == '__main__':
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, log_level='info', reload=True)
vendor.py
from fastapi import APIRouter, status, File, UploadFile
#from lxml import etree
import os
# file path
UPLOAD_DIR = r"c:\ack"
# check if the directory exists.
os.makedirs(UPLOAD_DIR, exist_ok=True)
# creates the endpoint path
router = APIRouter()
# POST Ack
@router.post("/ack/", status_code=status.HTTP_201_CREATED)
async def upload_ack(file: UploadFile = File(...)):
# define the complete path where the file will be saved.
file_location = os.path.join(UPLOAD_DIR, file.filename)
with open(file_location, "wb") as f:
f.write(await file.read())
return {"message": f"The file '{file.filename}' has been successfully saved into the server."}
As described in this answer, and demonstrated in this answer as well, when using FastAPI/Starlette's UploadFile
(you might want to have a look at Starlette's documentation on UploadFile
too), files are uploaded as multipart/form-data
. Example of how the backend should look like can be found below:
from fastapi import File, UploadFile
@app.post("/upload")
async def upload(file: UploadFile = File(...)):
pass
Hence, in Postman, you should select Body
-> form-data
and enter the key (i.e., parameter name) given for the UploadFile
object in your API endpoint—in your case and the example above, that is file
, since the parameter is defined as file: UploadFile = File(...)
—then select File
from the drop-down menu next to the key you just entered in Postman, and finally, upload your file in the Value
section by clicking on the Select files
button. In case of uploading multiple files, e.g., files: List[UploadFile] = File(...)
, the key should then be files
, for instance.
Instead, if you would like to use the binary
option in Postman to upload a file, as shown in your question (i.e., Body
-> binary
)—which would result in significantly better performance (especially, when you expect users to upload rather large files), not because of Postman, but due to how faster the uploading of file(s) becomes when processing the byte chunks as they arrive using FastAPI/Starlette's request.stream()
compared to using UploadFile
(more details are given in the linked answers below)—then, in that case, please have a look at this answer (see the Update section) and this answer on how you should have the API endpoint implemented in your backend.