Fastapi - UploadFile not working with HTML forms while it works in Swagger /docs

Viewed 843

I'm trying to replicate uploading a file which works with the /docs of Swagger/Fastapi and process it with Pandas. However, I get different types of errors when I'm trying it with HTML forms and it doesn't process the uploaded file. The last code I tried is the below and it gives back a 405 Method not Allowed error.

@app.get("/upload-test/")
def form_post(request: Request):
    """Displays the form to create a project"""
    return templates.TemplateResponse('upload-alerts.html', context={'request': request})


@app.get("/upload-test/file")
def form_post(request: Request):
    """Displays the form to create a project"""
    return {"message": "Upload success"}


@app.post("/upload-test/")
async def form_post(request: Request,
                    file: UploadFile = File(...)
                    ):
    """Uploads the file and processes it in Pandas"""
    contents = await file.read()
    test_data = io.BytesIO(contents)
    df = pd.read_csv(test_data, sep=";")
    df.to_sql("alert_test", if_exists="replace", con=database.SQLALCHEMY_DATABASE_URL, index=False)
    return {"filename":file.filename}

And the HTML:

<form action="file" enctype="multipart/form-data" method="post" autocomplete="off">
    <div class="mb-3">
        <div class="bg-light p-5 rounded-lg m-3">
            <label for="file" class="form-label">File Input</label>
            <input class="form-control" type="file" id="file" name="file">
        </div>
    </div>

    <div class="bg-light rounded-lg m-3">
        <div class="d-grid gap-2">
            <button class="btn btn-primary" type="button submit"><i class="bx bxs-cloud-upload"
                    style="font-size:1.4em;"></i> Upload Alerts</button>
        </div>
    </div>
</form>

Not sure what I'm missing here.. :/

**UPDATE**

Thanks to fchancel's answer I found that I had to change the following lines:
@app.get("/upload-test")  # So remove the last forward slash in get
@app.post("/upload-test")  # Remove also the last forward slash in post

In the HTML change the form action to "upload-test" to match it to the get/post:

<form action="upload-test" enctype="multipart/form-data" method="post" autocomplete="off">
1 Answers

You receive a 405 error because <form action="file" method='post'....> has the post method while your "/upload-test/file " endpoint is a GET. So, indeed, the 405 error makes sense.

So, you need to match the method between your form and your endpoint.

Related