Search code examples
pythonfile-uploadmultipartinternal-server-errorfastapi

Python FastAPI: Uploading Text file gives internal server error


I'm using FastAPI to write an API to upload text files and to read the txt file contents.

@app.post('/read_txt_file', response_class=PlainTextResponse)
async def upload_file_and_read(file: UploadFile = File(...)
                      , fileExtension: str = Form(...)):
 
    if(fileExtension == 'txt'):
        raw_txt = readTxt(file)
        raw_txt = raw_txt.decode()

    return raw_txt


def readTxt(file):
    return file.read()

This code above throws internal server error. Can I know how to correct it?

Logs:

File "/home/readerProject/.venv/lib/python3.7/site-packages/fastapi/routing.py", line 183, in app dependant=dependant, values=values, is_coroutine=is_coroutine File "/home/readerProject/.venv/lib/python3.7/site-packages/fastapi/routing.py", line 133, in run_endpoint_function return await dependant.call(**values)

File "/home/readerProject/api.py", line 28, in upload_file_and_read raw_txt = raw_txt.decode()

AttributeError: 'coroutine' object has no attribute 'decode' /home/readerProject/.venv/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py:396: RuntimeWarning: coroutine 'UploadFile.read' was never awaited
self.transport.close() RuntimeWarning: Enable tracemalloc to get the object allocation traceback


Solution

  • You have to call the readTxt(...) function with await syntax as

    raw_txt = await readTxt(file)
             ^^^^^^^

    Minimal verifiable example

    from fastapi import FastAPI, UploadFile, File
    
    app = FastAPI()
    
    
    @app.post('/read_txt_file')
    async def upload_file_and_read(
            file: UploadFile = File(...),
    ):
        if file.content_type.startswith("text"):
            text_binary = await readTxt(file) # call `await`
            response = text_binary.decode()
        else:
            # do something
            response = file.filename
    
        return response
    
    
    def readTxt(file):
        return file.read()
    

    As a side note, you can retrieve the context type by inspecting the file.content_type which can be used to identify the file extension.