4

I have an application that stores files and additional information e.g. author, comments DB. I can pass an file to FastAPI, but getting issue by passing it together with parameters.

I checked following question How to add multiple body params with fileupload in FastAPI? and this issue [QUESTION] Use UploadFile in Pydantic model #657 but without success.

I tried 2 definitions in the FastAPI endpoint

Option 1

class Properties(BaseModel):
   language: Optional[str] = None
   author: Optional[str] = None

@app.post("/uploadfile/")
async def uploadfile(params: Properties, file: UploadFile = File(...)):
    #internal logic

Option 2

@app.post("/uploadfile/")
async def uploadfile(file: UploadFile = File(...),
                         language: str = Form(...),
                         author: Optional[str] = Form(None)):
   #internal logic

Client code: Following code is used on client side, but response is 422 Unprocessable Entity for both options.

with open(path, 'rb') as f:
     response = requests.post('http://localhost:8005/uploadfile/', data={'language':'en', 
     'author':'me'}, files={'file': f})

Both options can't be tested from swagger, there I am getting response: value is not a valid dict. Data looks good for me, but maybe I am missing something.

It seems that the client code is wrong, but also there I tried several changes without success.

In advance, thanks for your support!

Solution that works for me

As 'Drdilyor' wrote in his comment I have use option 2, as we are sending file. My issue was within order of arguments. After changing them everything starts working.

Kosta
  • 45
  • 2
  • 7

1 Answers1

4

Per this issue, In my opinion it is an HTTP limitation, we have to either use application/json or multipart/formdata, but not both. And since we are uploading files, multipart/formdata has to be used. This code (somehow) works:

@app.post("/uploadfile/")
async def uploadfile(author: Optional[str] = Form(...),
                     language: Optional[str] = Form(...),
                     file: UploadFile = File(...)):

I tested it with curl http://localhost:8000/uploadfile/ -X POST -F author=me -F language=en -F file=@/path/to/file, not sure about requests

You could also use query params as well i think

Drdilyor
  • 1,250
  • 1
  • 12
  • 30
  • 1
    Thanks, for your help. I added information to my post. Client code that I was using initially is working now with Option 2. Issue was in the order of the arguments. – Kosta May 28 '21 at 11:09