Here are two options for uploading a file to a FastAPI application, using JavaScript in the frontend. Option 1 demonstrates a Fetch API approach, while Option 2 uses the Axios HTTP client.
If one would like to upload the file through an HTML <form> instead, please have a look at Method 1 of this answer. For multiple files uploading, this, as well this and this demonstrate on how to achieve that, using either fetch or axios. For a faster uploading file approach than using UploadFile—especially, when dealing with uploading rather large files in size—please take a look at the "Update" section of this answer.
Working Example
The FastAPI backend should be the same for both options below and is as follows:
app.py
from fastapi import File, UploadFile, Request, FastAPI, HTTPException
from fastapi.templating import Jinja2Templates
import aiofiles
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.post("/upload")
async def upload(file: UploadFile = File(...)):
try:
contents = await file.read()
async with aiofiles.open(file.filename, 'wb') as f:
await f.write(contents)
except Exception:
raise HTTPException(status_code=500, detail='Something went wrong')
finally:
await file.close()
return {"message": f"Successfuly uploaded {file.filename}"}
@app.get("/")
def main(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
Option 1 (using fetch)
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Upload File</title>
</head>
<body>
<input type="file" id="fileInput"><br>
<input type="button" value="Upload" onclick="uploadFile()">
<script type="text/javascript">
function uploadFile() {
var file = document.getElementById('fileInput').files[0];
if (file) {
var formData = new FormData();
formData.append('file', file);
fetch('/upload', {
method: 'POST',
body: formData,
})
.then(response => {
console.log(response);
})
.catch(error => {
console.error(error);
});
}
}
</script>
</body>
</html>
Option 2 (using axios)
CDN links for axios, if needed, could be found on either the official Axios website or CDNJS.
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Upload File</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<input type="file" id="fileInput"><br>
<input type="button" value="Upload" onclick="uploadFile()">
<script type="text/javascript">
function uploadFile() {
var file = document.getElementById('fileInput').files[0];
if (file) {
var formData = new FormData();
formData.append('file', file);
axios({
method: 'post',
url: '/upload',
data: formData,
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
console.log(response);
})
.catch(error => {
console.error(error);
});
}
}
</script>
</body>
</html>
The below should work as well:
axios.post('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});