2

I am trying to upload file (csv) to FastAPI POST endpoint.

This is the server code:

@app.post("/csv/file/preview")
async def post_csv_file_preview(file: UploadFile):
    """

    :param file:
    :return:
    """
    contents = file.file.read()
    print(contents)

But contents is empty if the file is small. If I increase the file content (add new lines in the csv file), without any others changes, it is working.

If I directly get the request body, the file content is returned normally.

print(await request.body())

The problem is only with my production server, not localally:

PYTHONPATH=/var/www/api/current /var/www/api/current/venv/bin/python /var/www/api/current/venv/bin/uvicorn main:app --reload --port=8004

I dont understand

Chris
  • 18,724
  • 6
  • 46
  • 80
Bastien D
  • 1,395
  • 2
  • 14
  • 26
  • Does this answer your question? [How to Upload File using FastAPI?](https://stackoverflow.com/questions/63048825/how-to-upload-file-using-fastapi) – Chris Sep 07 '22 at 09:01
  • 1
    Also, please make sure that you haven't already read the file contents, before calling `file.file.read()`. If so, you need to use the `.seek()` method to set the current position of the cursor to `0` (i.e., rewind the cursor to the start of the file), as described in Option 1 of [this answer](https://stackoverflow.com/a/70653605/17865804). – Chris Sep 07 '22 at 09:05
  • No. I send my file with Insomnia for test in production – Bastien D Sep 07 '22 at 09:08
  • Also, I would not recommend using `async def` endpoint while reading the file contents in a `sync` way. Please have a look at [this answer](https://stackoverflow.com/a/70667530/17865804) and [this answer](https://stackoverflow.com/a/71517830/17865804) for more details. – Chris Sep 07 '22 at 09:14
  • Hoo yes it's ok with seek. Thanks. But is so curious. This file is read only once by request. – Bastien D Sep 07 '22 at 09:17
  • I've encountered the same exact problem: file is only read once, `seek(0)` helps, and it can only be reproduced on production. I've narrowed down "small file" size to 9828 bytes - everything above that reads OK on the first try. Still no idea what causes this, though. – WeirdCarrotMonster Sep 15 '22 at 11:12

1 Answers1

2

Thanks to the comment from Chris, I solved my problem by adding the .seek() method before reading the file contents.

@app.post("/csv/file/preview")
def post_csv_file_preview(file: UploadFile):
    """

    :param file:
    :return:
    """
    file.file.seek(0)
    contents = file.file.read()
    print(contents)
Chris
  • 18,724
  • 6
  • 46
  • 80
Bastien D
  • 1,395
  • 2
  • 14
  • 26