简体   繁体   中英

How to post an image file with a list of strings using FastAPI?

I have tried a lot of things, but it doesn't seem to work. Here is my code:

@app.post("/my-endpoint")
async def my_func(
    languages: List[str] = ["en", "hi"], image: UploadFile = File(...)
):

The function works fine when I remove one of the parameters, but with both of the parameters, the retrieved list comes out to be like ["en,hi"] , whereas I want it to be ["en, "hi] .

I am not even sure if my approach is correct, hence the broader question, if this approach is not right then how can I post a list and an image together?

Your function looks okay. The problem for that behaviour has to do with how Swagger (I am assuming you are using it for testing, as I did myself and noticed the exact behaviour) handles the list items. For some reason, Swagger adds all items as a single item in the list, separated by comma (ie, ["en, hi, ..."], instead of ["en", "hi", ...]).

Testing the code with Python requests and sending the languages' list in the proper way, it works just fine. To fix, however, the behaviour by Swagger, or any other tool that might behave the same, you could check the length of the list that is received in the function, and if it is just 1 (meaning that it includes a single item), then split this item by comma to get a new list of languages.

Below is a working example:

app.py

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

app = FastAPI()

@app.post("/submit")
async def submit(languages: List[str] = ["en", "hi"], image: UploadFile = File(...)):
        if (len(languages) == 1):
            languages= [item.strip() for item in languages[0].split(',')]
        return {"Languages ": languages, "Uploaded filename": image.filename}

if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000, debug=True)

test.py

import requests

url = 'http://127.0.0.1:8000/submit'
image = {'image': open('sample.png', 'rb')}
#payload ={"languages": ["en", "hi"]}  # send languages as separate items
payload ={"languages": "en, hi"}  # send languages as a single item
resp = requests.post(url=url, data=payload, files=image) 
print(resp.json())

I solved this using Query parameters, This might be helpful for someone, though I think Chris' answer makes much more sense -

@app.post("/my-endpoint")
async def my_func(
    languages: List[str] = Query(["en", "hi"]), image: UploadFile = File(...)
):

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM