我正在try 创建一个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函数时,下载generated.docx文件.但是,docx文件始终是corrupted,并且不会打开.我试着使用txt文件,它工作得很好.我需要使用docx文件,我能做些什么?

推荐答案

在Axios GET请求中,您必须确保将responseType参数设置为blob.从API获得response之后,您需要将response.data传递给URL.createObjectURL()函数.下面是一个完整的工作示例,说明如何在前端使用Axios或Fetch API创建和下载文件(Document).该答案使用了来自thisthis答案以及答案herehere的方法和代码摘录.有关下面使用的方法的更多详细信息,请参考上面的答案.出于演示的目的,下面的示例使用Jinja2Templates,但是,以类似的方式,您可以在您的ReactJS应用程序中使用下面的脚本.

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)

使用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(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>

使用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>

Javascript相关问答推荐

使用print This时, map 容器已在LeafletJS中初始化

如何使用侧边滚动按钮具体滚动每4个格?

点击按钮一次有文本出现和褪色,而不是点击两次?(html,CSS,JavaScript)

如何粗体匹配的字母时输入搜索框使用javascript?

使用useEffect,axios和useParams进行react测试

我怎么才能得到Kotlin的密文?

以Angular 实现ng-Circle-Progress时出错:模块没有导出的成员

用于在路径之间移动图像的查询

在Matter.js中添加从点A到另一个约束的约束

如何在Angular拖放组件中同步数组?

元素字符串长度html

面对代码中的错误作为前端与后端的集成

为什么当我更新数据库时,我的所有组件都重新呈现?

如何防止ionic 输入中的特殊字符.?

在Odoo中如何以编程方式在POS中添加产品

将范围 Select 器添加到HighChart面积图

如何在AG-Grid文本字段中创建占位符

如何向内部有文本输入字段的HTML表添加行?

输入数据覆盖JSON文件

JSON Web令牌(JWT)错误:RSA密钥对的签名无效