Search code examples
pythonfile-uploadpython-requestsfastapi

How to pass string and multiple files using FastAPI and Python requests?


I am using the following FastAPI endpoint that accepts multiple files:

from fastapi import Request, FastAPI, File, UploadFile
from typing import List
import uvicorn

app = FastAPI()

@app.post("/multiplefiles")
async def _file_upload(keywords, files: List[UploadFile] = File(...)): #create_file
    return {"len_files": keywords}

I would like to first input the keywords parameter, then the list of files, but I cannot find a way to perform a valid post request:

import requests

files = (("keywords", "key1"),
    [
    ('files', open('files\file1.pdf', 'rb')), 
    ('files', open('files\file2.pdf', 'rb'))
    ]
)

response = requests.post('http://127.0.0.1:3000/multiplefiles', files=files)
print(response.json())

If I only upload the files as a list of tuple work, but I do not know how to pass in the keywords parameter.


Solution

  • Option 1 - Define query parameter as str

    In the way the keywords parameter is defined in your endpoint is expected to be a query parameter. If you expect it to be a single string value, you can define it using str as follows:

    Server side:

    @app.post("/")
    def upload(keywords: str, files: List[UploadFile] = File(...)):
        return {"keywords": keywords}
    

    Since it is expected as query parameter, you should use the params argument in Python requests, in order to pass query parameters, as described here. Example:

    Client side:

    url = 'http://127.0.0.1:8000/'
    data = {'keywords': 'key1'}
    r = requests.post(url, files=files, params=data)
    print(r.json())
    

    You could also pass it directly to the URL instead:

    url = 'http://127.0.0.1:8000?keywords=key1'
    

    Option 2 - Define query parameter as List

    If you are sending a list of keywords, you have to declare the keywords query parameter with a type of List (or list in Python 3.9+), and define it explicitly with Query, so that it can receive a list of values, or in other words, to receive multiple values—see related answers here, here and here (for arbitrary query parameters see this and this). Example:

    Server side:

    from fastapi import Query
    
    @app.post("/")
    def upload(keywords: List[str] = Query(...), files: List[UploadFile] = File(...)):
        return {"keywords": keywords} 
    

    Client side:

    url = 'http://127.0.0.1:8000/'
    data = {'keywords': ['key1', 'key2']}
    r = requests.post(url, files=files, params=data)
    print(r.json())
    

    If you would like to add the list of keywords to the URL's query string yourself, it should then look like this:

    url = 'http://127.0.0.1:8000/?keywords=key1&keywords=key2'
    

    See this answer for more details.

    Option 3 - Use Form parameters

    If you would like to use Form parameters instead to pass additional data along with files, please have a look at this answer.