Skip to content

POST with UploadFile returns 422 when called by client application #1911

@aretasg

Description

@aretasg

Example

import os
import shutil
from pathlib import Path
from tempfile import TemporaryDirectory

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

def save_upload_file(upload_file: UploadFile, destination: Path) -> None:

    # https://github.com/tiangolo/fastapi/issues/426#issuecomment-542828790

    try:
        with open(destination, "wb") as buffer:
            shutil.copyfileobj(upload_file.file, buffer)
    finally:
        upload_file.file.close()


@app.post("/upload_two_files", summary="Upload and save two files")
def upload_sequences(
    first_file: UploadFile = File(...),
    second_file: UploadFile = File(...)
    ):

    app_root = os.path.dirname(os.path.abspath(__file__))
    upload_folder = os.path.join(app_root, 'upload-folder')
    prefix = os.path.abspath(upload_folder)

    temp_dir = TemporaryDirectory(prefix=prefix)

    first_file_filename = first_file.filename
    attributes_file_location = os.path.join(temp_dir.name, first_file_filename)
    save_upload_file(first_file, first_file_file_location)

    second_file_filename = second_file.filename
    second_file_file_location = os.path.join(temp_dir.name, second_file_filename)
    save_upload_file(second_file, second_file_file_location)

    response = {"first_file": first_file_filename, "second_file": second_file_filename}

    return response

Description

I am trying to upload two files and process them.
It works from OpenAPI/Swagger UI (/docs) and from Postman with 'Content-Type: multipart/form-data'.
However, when a KNIME workflow I have inherited is making a call the code generates 422.
I have checked the KNIME node and it also contains 'Content-Type: multipart/form-data'. You can read more about the node here.
I have tried changing headers for the past few days and about to give up but would really prefer to keep FastAPI instead of turning back to Flask. I realize it's a very KNIME specific question but I would appreciate any advice at this point.

Environment

  • OS: Linux
  • FastAPI Version: 0.60.1
  • Python version: 3.8

Additional context

Before I had this piece of Flask code which did work with the client code:

import os
from tempfile import TemporaryDirectory

from werkzeug.utils import secure_filename
from flask import Flask, request

app = Flask(__name__)

@app.route('/upload_two_files', methods=['POST'])
def upload_sequences():

    first_file = request.files['first_file']
    second_file = request.files['second_file']

    app_root = os.path.dirname(os.path.abspath(__file__))
    upload_folder = os.path.join(app_root, 'upload-folder')
    prefix = os.path.abspath(upload_folder)

    temp_dir = TemporaryDirectory(prefix=prefix)

    first_file_filename = secure_filename(first_file.filename)
    first_file_location = os.path.join(prefix, first_file_filename)
    first_file.save(first_file_location)

    second_file_filename = secure_filename(second_file.filename)
    second_file_location = os.path.join(prefix, second_file_filename)
    second_file_file.save(second_file_location)

    response = {"first_file": first_file_filename, "second_file": second_file_filename}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions