In the Axios GET
request, you have to make sure the responseType
parameter is set to blob
. Once you get the response
from the API, you will need to pass the Blob
object (i.e., response.data
) to the URL.createObjectURL()
function. Below is a fully working example on how to create and download a file (Document
), using either Axios or Fetch API in the frontend. This answer utilises methods and code excerpts from this and this answer, as well as the answers here and here. Plesase refer to the above answers for more details on the methods used below. For demo purposes, the below example uses Jinja2Templates
, but, in a similar way, you can use the scripts below in your ReactJS app.
app.py
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import FileResponse
from docx import Document
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get('/')
def main(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.post("/create")
def create_file():
document = Document()
document.add_heading("file generated", level=1)
document.add_paragraph("test")
document.save('generated_file.docx')
return {"status":"Done!"}
@app.get("/download")
def download_generated_file():
file_path = "generated_file.docx"
return FileResponse(file_path, media_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document', filename=file_path)
Using Axios
tempaltes/index.htnl
<!DOCTYPE html>
<html>
<head>
<title>Create and Download a Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js"></script>
</head>
<body>
<input type="button" value="Create Document" onclick="createFile()">
<div id="response"></div><br>
<input type="button" value="Download Document " onclick="downloadFile()">
<script>
function createFile() {
axios.post('/create', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => {
document.getElementById("response").innerHTML = JSON.stringify(response.data);
})
.catch(error => {
console.error(error);
});
}
function downloadFile() {
axios.get('/download', {
responseType: 'blob'
})
.then(response => {
const disposition = response.headers['content-disposition'];
filename = disposition.split(/;(.+)/)[1].split(/=(.+)/)[1];
if (filename.toLowerCase().startsWith("utf-8''"))
filename = decodeURIComponent(filename.replace("utf-8''", ''));
else
filename = filename.replace(/['"]/g, '');
return response.data;
})
.then(blob => {
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a); // append the element to the dom
a.click();
a.remove(); // afterwards, remove the element
})
.catch(error => {
console.error(error);
});
}
</script>
</body>
</html>
Using Fetch API
tempaltes/index.htnl
<!DOCTYPE html>
<html>
<head>
<title>Create and Download a Document</title>
</head>
<body>
<input type="button" value="Create Document" onclick="createFile()">
<div id="response"></div><br>
<input type="button" value="Download Document" onclick="downloadFile()">
<script>
function createFile() {
fetch('/create', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.text())
.then(data => {
document.getElementById("response").innerHTML = data;
})
.catch(error => {
console.error(error);
});
}
function downloadFile() {
fetch('/download')
.then(response => {
const disposition = response.headers.get('Content-Disposition');
filename = disposition.split(/;(.+)/)[1].split(/=(.+)/)[1];
if (filename.toLowerCase().startsWith("utf-8''"))
filename = decodeURIComponent(filename.replace("utf-8''", ''));
else
filename = filename.replace(/['"]/g, '');
return response.blob();
})
.then(blob => {
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a); // append the element to the dom
a.click();
a.remove(); // afterwards, remove the element
})
.catch(error => {
console.error(error);
});
}
</script>
</body>
</html>