如何使用 ReactJS 在前端使用 Axios,在后端使用 FastAPI 下载文件?

Ahm*_*hbe 5 javascript web reactjs axios fastapi

我正在尝试创建一个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!"}
Run Code Online (Sandbox Code Playgroud)

然后使用以下代码将创建的docx文件作为 a发送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)
Run Code Online (Sandbox Code Playgroud)

在客户端(我正在使用 ReactJS):

@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!"}
Run Code Online (Sandbox Code Playgroud)

调用函数generated.docx时会下载文件。downloadFile但是,该docx文件始终已损坏并且无法打开。我尝试使用txt文件,效果很好。我需要使用docx文件,我该怎么办?

Chr*_*ris 5

在axiosGET请求中,您必须确保responseType参数设置为blob。从 API获取 后response,您需要将Blob对象(即response.data)传递给URL.createObjectURL()函数。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)
Run Code Online (Sandbox Code Playgroud)

使用 Axios

模板/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>
Run Code Online (Sandbox Code Playgroud)

使用获取 API

模板/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>
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

8170 次

最近记录:

2 年,3 月 前