[英]How to download a file using ReactJS with Axios in the frontend and FastAPI in the backend?
I am trying to create a docx
file and send it to the frontend client app, so that it can be downloaded to the user's local machine.我正在尝试创建一个
docx
文件并将其发送到前端客户端应用程序,以便可以将其下载到用户的本地计算机。 I am using FastAPI for the backend.我在后端使用 FastAPI。 I am using
python-docx
library also to create the Document
.我也在使用
python-docx
库来创建Document
。
The code below is used to create a docx
file and save it to the server.下面的代码用于创建一个
docx
文件并将其保存到服务器。
@app.post("/create_file")
async def create_file(data: Item):
document = Document()
document.add_heading("file generated", level=1)
document.add_paragraph("test")
document.save('generated_file.docx')
return {"status":"Done!"}
The below code is then used to send the created docx
file as a FileResponse
to the client.然后使用下面的代码将创建的
docx
文件作为FileResponse
发送到客户端。
@app.get("/generated_file")
async def download_generated_file():
file_path = "generated_file.docx"
return FileResponse(file_path, media_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document', filename=file_path)
On Client side (I am using ReactJS):在客户端(我正在使用 ReactJS):
createFile = async () => {
const data = {
start: this.state.start,
end: this.state.end,
text: this.state.text,
};
await axios.post("http://localhost:8000/create_file", data).then(() => {
console.log("processing completed!");
});
};
downloadFile = async () => {
await axios.get("http://localhost:8000/generated_file").then((res) => {
const url = URL.createObjectURL(new Blob([res.data]));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "generated.txt");
link.click();
});
};
The generated.docx
file gets downloaded when downloadFile
function is called.调用
downloadFile
function 时会下载generated.docx
的.docx 文件。 However, the docx
file is always corrupted and doesn't open.但是,
docx
文件总是损坏并且无法打开。 I tried using txt file and it works fine.我尝试使用 txt 文件,它工作正常。 I need to use docx file, so what can I do?
我需要使用docx文件,我该怎么办?
In the Axios GET
request, you have to make sure the responseType
parameter is set to blob
.在 Axios
GET
请求中,您必须确保responseType
参数设置为blob
。 Once you get the response
from the API, you will need to pass the response.data
to the URL.createObjectURL()
function.从 API 获得
response
后,您需要将response.data
传递给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.下面是一个关于如何创建和下载文件(
Document
)的完整示例,在前端使用 Axios 或 Fetch API。 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.出于演示目的,以下示例使用
Jinja2Templates
,但以类似的方式,您可以在 ReactJS 应用程序中使用以下脚本。
app.py应用程序.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)
tempaltes/ index.htnl模板/ 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(data => {
var url = window.URL.createObjectURL(data);
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>
tempaltes/ index.htnl模板/ 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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.