![](/img/trans.png)
[英]How do I download a file returned from FastAPI backend using Fetch API at the frontend?
[英]How to download a file using ReactJS with Axios in the frontend and FastAPI in the backend?
我正在嘗試創建一個docx
文件並將其發送到前端客戶端應用程序,以便可以將其下載到用戶的本地計算機。 我在后端使用 FastAPI。 我也在使用python-docx
庫來創建Document
。
下面的代碼用於創建一個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!"}
然后使用下面的代碼將創建的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)
在客戶端(我正在使用 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();
});
};
調用downloadFile
function 時會下載generated.docx
的.docx 文件。 但是, docx
文件總是損壞並且無法打開。 我嘗試使用 txt 文件,它工作正常。 我需要使用docx文件,我該怎么辦?
在 Axios GET
請求中,您必須確保responseType
參數設置為blob
。 從 API 獲得response
后,您需要將response.data
傳遞給URL.createObjectURL()
function。 下面是一個關於如何創建和下載文件( Document
)的完整示例,在前端使用 Axios 或 Fetch API。 這個答案利用了這個和這個答案的方法和代碼摘錄,以及這里和這里的答案。 有關以下使用的方法的更多詳細信息,請參閱上述答案。 出於演示目的,以下示例使用Jinja2Templates
,但以類似的方式,您可以在 ReactJS 應用程序中使用以下腳本。
應用程序.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)
模板/ 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>
模板/ 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.