avatarNg Wai Foong

Summary

The web content provides a guide on how to save uploaded files in FastAPI, detailing the process for both single and multiple file uploads.

Abstract

The article "How to Save Uploaded Files in FastAPI" is a step-by-step tutorial that addresses the lack of a built-in file-saving function in FastAPI, which is available in Flask as file.save. It explains how to handle file uploads using FastAPI's UploadFile class, which stores files in memory or on disk depending on their size. The tutorial covers the installation of python-multipart for receiving uploaded files, the attributes and methods of UploadFile, and the implementation of file saving using shutil.copyfileobj(). It also extends the solution to handle multiple file uploads, providing code examples for both scenarios. The article concludes by summarizing the key points learned and provides references for further reading on FastAPI features.

Opinions

  • The author suggests that FastAPI's approach to file handling, while not as straightforward as Flask's, can be effectively implemented using standard Python libraries.
  • The article implies that developers transitioning from Flask to FastAPI may initially find the lack of a file-saving wrapper inconvenient but can appreciate the flexibility offered by FastAPI's UploadFile class.
  • The author emphasizes the importance of understanding the UploadFile class's methods and attributes, particularly for developers who are new to FastAPI.
  • By providing a detailed guide on saving files, the author conveys that this functionality is essential for many web applications and that FastAPI's robustness in handling file uploads is a valuable feature.
  • The recommendation to read additional articles on FastAPI indicates the author's view that continuous learning and exploration of the framework are beneficial for developers.

How to Save Uploaded Files in FastAPI

Step-by-step guide to receive files and save them locally

Image by Author

The topic for today is on saving images or text files that users have uploaded to your FastAPI server locally in disk. If you have used Flask before, you should know that it comes with its own built-in file.save function for saving files. Unfortunately, such feature is not present in FastAPI at the time of this writing. In this tutorial, you will learn to implement this functionality based on your own use cases.

Single File

For your information, the bare minimum code for a simple FastAPI server that accepts an image or a file uploaded via FormData is as follows:

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/image")
async def image(image: UploadFile = File(...)):
    return {"filename": image.filename}

Python multipart

In order to receive the uploaded files, you need to install python-multipart. Run the following command in your terminal if you have to install it in your virtual environment.

pip install python-multipart

FastAPI UploadFile

UploadFile uses Python SpooledTemporaryFile object which means that it is will be stored in memory as long the file size is within the size limit. Otherwise, it will be stored in disk once it exceeded the size limit.

Since it inherits from Starlette, it has the following attributes:

  • filename — Name of the file. It is based on the original file name uploaded.
  • content_type — Content type of the file. For example, an JPEG image file should be image/jpeg.
  • file — Python file object.

In addition, UploadFile also comes with four additional async functions. Normally, you should call them together using await in a normal async function. In FastAPI, async methods are designed to run the file methods in a threadpool and it will await them. Hence, you can call these functions without await syntax.

  • write(data) — Writes data to the file. Accepts either string or bytes.
  • read(size) — Reads n number of bytes or characters of the file based on the input parameter. Accepts an integer.
  • seek(offset) — Moves to the byte or character position in the file. Using seek(0) will go to the beginning of the file.
  • close() — Closes the file

Saving File

Flask has a file.save wrapper function which allows you to save the uploaded file locally in your disk. The wrapper is based on the shutils.copyfileobj() function which is part of the Python standard library. However, there is no such implementation for FastAPI yet at the time of this writing.

You can easily implement it inside FastAPI server. First, you need to import the shutil module.

import shutil

The basic structure and code looks something like this.

with open("destination.png", "wb") as buffer:
    shutil.copyfileobj(image.file, buffer)

Simply call it inside your FastAPI methods. Have a look at the following code snippet.

async def image(image: UploadFile = File(...)):
    with open("destination.png", "wb") as buffer:
        shutil.copyfileobj(image.file, buffer)
    
    return {"filename": image.filename}

Re-run your FastAPI server and submit a form with a file attached to it from your front-end code. You should see a new file being generated based on the path that you have specified.

Multiple Files

For handling multiple files upload, you need to import the following statement

from typing import List

Next, modify the FastAPI method which take in a List of UploadFile.

async def image(images: List[UploadFile] = File(...)):

Simply loop it using for loop and implement the save logic inside it.

for image in images:
    with open(image.filename, "wb") as buffer:
        shutil.copyfileobj(image.file, buffer)

For more information on FastAPI, it is highly recommended to read the following articles:

Conclusion

Let’s recap what we have learned today.

We started off with a simple problem statement explaining the lack of wrapper function in FastAPI to save uploaded files.

Next, we explored in-depth on the fundamental concept behind UploadFile and how to use it inside FastAPI server.

We have also implemented a simple file saving functionality using the built-in shutil.copyfileobj method. Besides, we have also tried extending our server to handle multiple files upload.

Thanks for reading this piece. Hope to see you again in the next article!

References

  1. FastAPI Request Files
  2. Save an Uploaded File FastAPI Github Issue
Fastapi
Python
Programming
Multipart Form Data
DevOps
Recommended from ReadMedium