FastAPI is an awesome and simple framework for building APIs (application programming interfaces). Among the various features of FastAPI out of the box
we will be exploring how to include an endpoint whereby we can upload a json file and return another file that we can download.
In this tutorial we will create an endpoint for uploading and downloading files using FastAPI.
So what is the use case of this? In case you build a service where you want users to send a file format for processing eg json to yaml converter or json to latex or pdf convertion, understanding how to upload and download files with FastAPI will be helpful.
Let us start.
How to Upload Files in FastAPI
FastAPI provides a class object called UploadFile or Files for accepting file format via http request from an endpoint. For that to work you will need to install
python-multipart package for handling the upload feature via pip.
Below is the simple code
from fastapi import FastAPI, UploadFile
from fastapi.exceptions import HTTPException
import uvicorn
import json
# Init App
app = FastAPI()
@app.post("/file/upload")
def upload_file(file: UploadFile):
if file.content_type != "application/json":
raise HTTPException(400,detail="Invalid document type")
else:
data = json.loads(file.file.read())
return {"content":data ,"filename":file.filename}
if __name__ == '__main__':
uvicorn.run(app,host="127.0.0.1",port=8000)
How to Create an Endpoint for Downloading Files
With FastAPI FileResponse object, you can return files via your HTTP response.
The recommended way is to save the file in a directory and transmitting via the FileResponse class object as below.
@app.post("/file/uploadndownload")
def upload_n_downloadfile(file: UploadFile):
"""Return a YAML FIle for the uploaded JSON File"""
if file.content_type != "application/json":
raise HTTPException(400,detail="Invalid document type")
else:
json_data = json.loads(file.file.read())
new_filename = "{}_{}.yaml".format(os.path.splitext(file.filename)[0],timestr)
# Write the data to a file
# Store the saved file
SAVE_FILE_PATH = os.path.join(UPLOAD_DIR,new_filename)
with open(SAVE_FILE_PATH,"w") as f:
yaml.dump(json_data,f)
# Return as a download
return FileResponse(path=SAVE_FILE_PATH,media_type="application/octet-stream",filename=new_filename)
We are using a media_type or mime type of application/octet-stream since this support multiple file types or mime types.
Now let us combine the two into building a service to upload JSON files and return a valid YAML File for download.
Full Code for download and upload
import time
from fastapi import FastAPI, UploadFile
from fastapi.exceptions import HTTPException
from fastapi.responses import FileResponse
import uvicorn
import json
import os
import yaml
app = FastAPI()
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
UPLOAD_DIR = os.path.join(BASE_DIR, "uploads")
timestr = time.strftime("%Y%m%d-%H%M%S")
@app.get("/")
def read_root():
return {"Hello": "FastAPI"}
@app.post("/file/upload")
def upload_file(file: UploadFile):
if file.content_type != "application/json":
raise HTTPException(400, detail="Invalid document type")
else:
data = json.loads(file.file.read())
return {"content": data, "filename": file.filename}
@app.post("/file/uploadndownload")
def upload_n_downloadfile(file: UploadFile):
"""Return a YAML FIle for the uploaded JSON File"""
if file.content_type != "application/json":
raise HTTPException(400, detail="Invalid document type")
else:
json_data = json.loads(file.file.read())
new_filename = "{}_{}.yaml".format(os.path.splitext(file.filename)[0], timestr)
# Write the data to a file
# Store the saved file
SAVE_FILE_PATH = os.path.join(UPLOAD_DIR, new_filename)
with open(SAVE_FILE_PATH, "w") as f:
yaml.dump(json_data, f)
# Return as a download
return FileResponse(
path=SAVE_FILE_PATH,
media_type="application/octet-stream",
filename=new_filename,
)
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
You can check out the video tutorial for more
Thank You For Your Time
Jesus Saves @ JCharisTech
By Jesse E.Agbe