如何在Python中生成DOCX并将其保存在内存中?

2023-11-23

我的任务是从模板生成 DOCX 文件,然后通过 Flask 提供该文件。我用python-docx-模板它只是 python-docx 的包装器,允许使用 jinja 模板。

最后他们建议使用 StringIO 仅将文件保存在内存中,所以我的代码如下所示:

def report_doc(user_id):
    # Prepare the data...

    from docxtpl import DocxTemplate

    doc = DocxTemplate(app.root_path+'/templates/report.docx')
    doc.render({
        # Pass parameters
    })
    from io import StringIO
    file_stream = StringIO()
    doc.save(file_stream)

    return send_file(file_stream, as_attachment=True, attachment_filename='report_'+user_id+'.docx')

保存时会抛出错误TypeError: string argument expected, got 'bytes'。谷歌搜索后,我发现这个答案上面说ZipFile需要 BytesIO。但是,当我用 BytesIO 替换 StringIO 时,它只返回一个空文件,因此它不会抛出任何错误,但绝对不会保存文件。

在这种情况下到底什么才有效呢?如果这里出现了完全错误的情况,那么一般情况下这怎么行?

谢谢你!

UPD:这是完整跟踪的例外情况save函数调用:

File "/ms/controllers.py", line 1306, in report_doc
    doc.save(file_stream)
  File "/.env/lib/python3.5/site-packages/docx/document.py", line 142, in save
    self._part.save(path_or_stream)
  File "/.env/lib/python3.5/site-packages/docx/parts/document.py", line 129, in save
    self.package.save(path_or_stream)
  File "/.env/lib/python3.5/site-packages/docx/opc/package.py", line 160, in save
    PackageWriter.write(pkg_file, self.rels, self.parts)
  File "/.env/lib/python3.5/site-packages/docx/opc/pkgwriter.py", line 33, in write
    PackageWriter._write_content_types_stream(phys_writer, parts)
  File "/.env/lib/python3.5/site-packages/docx/opc/pkgwriter.py", line 45, in _write_content_types_stream
    phys_writer.write(CONTENT_TYPES_URI, cti.blob)
  File "/.env/lib/python3.5/site-packages/docx/opc/phys_pkg.py", line 155, in write
    self._zipf.writestr(pack_uri.membername, blob)
  File "/usr/lib/python3.5/zipfile.py", line 1581, in writestr
    self.fp.write(zinfo.FileHeader(zip64))
TypeError: string argument expected, got 'bytes'

Using a BytesIO实例是正确的,但你需要倒回文件指针在将其传递给之前send_file:

确保文件指针位于数据的开头 在调用 send_file() 之前发送。

所以这应该有效:

import io
from docxtpl import DocxTemplate

def report_doc(user_id):
   # Prepare the data...

   doc = DocxTemplate(app.root_path+'/templates/report.docx')
   doc.render({
        # Pass parameters
   })

   # Create in-memory buffer
   file_stream = io.BytesIO()
   # Save the .docx to the buffer
   doc.save(file_stream)
   # Reset the buffer's file-pointer to the beginning of the file
   file_stream.seek(0)

   return send_file(file_stream, as_attachment=True, attachment_filename='report_'+user_id+'.docx')

(在 Firefox 上进行测试,我发现即使我指定了不同的文件名,浏览器也会不断从缓存中检索文件,因此您可能需要在测试时清除浏览器的缓存,或者在开发工具中禁用缓存(如果您的浏览器支持此功能),或者调整 Flask 的缓存控制设置).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Python中生成DOCX并将其保存在内存中? 的相关文章

随机推荐

  • ng 服务无法在 Docker 容器中工作

    我有这个Docker Compose 配置我只需创建一个 NodeJS 容器并在其中安装 Angular CLI After a docker compose up d 我可以在容器内通过 SSH 连接docker compose run
  • 将程序拆分为 4 个线程比单个线程慢

    过去一周我一直在编写一个光线追踪器 并且已经达到了足够多线程的程度 我尝试过使用 OpenMP 来并行化它 但是使用更多线程运行它实际上比使用一个线程运行它要慢 阅读其他类似的问题 尤其是有关 OpenMP 的问题 一个建议是 gcc 可以
  • Django 服务器错误:端口已在使用中

    重新启动 Django 服务器显示以下错误 this port is already running 此问题专门出现在 Ubuntu 上 而不是其他操作系统上 如何释放端口以重新启动服务器 更简单的解决方案只需键入sudo fuser k
  • 24小时制转换为12小时制?

    您好 我正在使用 Android 应用程序 我正在尝试弄清楚如何将 24 小时时间转换为 12 小时时间 Example 24 hour format 12 18 00 to 12 hour format 12 18pm 尝试使用Simpl
  • 将列表分割成 n 个几乎相等长度的分区[重复]

    这个问题在这里已经有答案了 我正在寻找一种快速 干净 Pythonic 的方法来将列表精确地划分为 n 个几乎相等的分区 partition 1 2 3 4 5 5 gt 1 2 3 4 5 partition 1 2 3 4 5 2 gt
  • select * from table_name where 列如 ' '

    我需要查找包含 html 代码 例如 nbsp 的记录但是当我尝试运行select from table name where column like nbsp 我收到提示询问 nbsp 的值 我猜数据库认为nbsp是一个参数 我想知道是否
  • 为什么 ad hoc ipa 在一台设备上安装失败,但在另一台具有相同 iOS 版本的设备上安装成功?

    我有一位客户 其 iPad 2 iOS 5 0 能够安装临时 ipa 但他的 iPhone 也是 iOS 5 0 完全相同的版本 在尝试使用 Windows iTunes 安装时在他的设备上收到以下消息 iTunes 同步 应用程序名称 安
  • 如何从 GitHub Actions 部署 AWS Amplify 应用程序?

    我想从 GitHub Actions 控制 Amplify 部署 因为 Amplify 自动构建 不提供GitHub环境 不观察 CI 的故障并无论如何都会进行部署 或者 要求我复制 CI 设置并在 Amplify 中重新运行它 不支持运行
  • ASP.NET 解析器错误无法加载后面的代码

    嘿我收到以下错误 解析器错误 描述 解析服务此请求所需的资源时发生错误 请查看以下特定解析错误详细信息并适当修改您的源文件 解析器错误消息 无法加载类型 AddToCart 来源错误 Line 1 Line 2 Line 3
  • 自动生成Java源代码

    我正在寻找一种方法 根据类中定义的字段 在现有 Java 源代码文件中自动生成新方法的源代码 本质上 我希望执行以下步骤 读取并解析SomeClass java 遍历源代码中定义的所有字段 添加源码方法someMethod Save Som
  • 什么是“程序类型已存在”?

    当我尝试构建我的项目时 我收到此错误 程序类型已存在 android support v4 accessibilityservice AccessibilityServiceInfoCompat Message kind ERROR tex
  • 角度反应形式:动态选择下拉值不具有约束力

    我有两个数据数组 AssociatedPrincipals 以前保存的数据 和 ReferencePrincipals 在下拉控件中填充的静态数据 我正在努力从 AssociatedPrincipals 获取先前的值以在 a 中显示 选择动
  • 如何转义 RMarkdown 块?

    我正在尝试将 RMarkdown 中的代码块的语法呈现为 pdf 最终输出应该是这样的 r some code 而不仅仅是 some code 可以在 RStudio 网站上找到解决此问题的最佳选项 请参阅有关将逐字 R 块放入 rmark
  • 将“if/else”与 OnClick 结合使用

    首先 是否可以直接在带有 onclick 属性的 html 中编写 if else 语句 如果是这样 为什么我的代码不起作用 所以这是一个按钮 Calc Input value 指的是文本输入 如果该字段为 0 或空白 我想显示错误消息 在
  • R:如何在没有辅助文件的情况下将光栅写入磁盘?

    我正在使用 R 中的 Raster 包以 ERMapper 格式 ers 编写数据集 但我对生成的 aux xml 辅助文件有问题 我实际上对此不感兴趣 简单的例子 rst lt raster ncols 15000 nrows 10000
  • cuda 中预取(通过 C 代码)

    我正在通过 C 代码在 CUDA Fermi GPU 中进行数据预取 Cuda 参考手册讨论了 ptx 级别代码的预取 而不是 C 级别代码的预取 任何人都可以向我提供一些有关通过 cuda 代码 cu 文件 预取的文档或内容吗 任何帮助
  • 使用 fputs() 将整数写入文件

    不可能做类似的事情fputs 4 fptOut 因为 fputs 不喜欢整数 我该如何解决这个问题 Doing fputs 4 fptOut 不是一个选项 因为我正在使用计数器值 关于什么 fprintf fptOut d yourCoun
  • 比较两个对象数组并检查它们是否具有共同元素

    如何在 MongoDB 中执行返回 id 的查询FirstArray and SecondArray 名称 字段中有共同的元素吗 这是集合结构 id ObjectId 58b8d9e3b2b4e07bff8feed5 FirstArray
  • 如何在 SwiftUI 中随时从子视图作为父视图访问数据?

    我是 SwiftUI 的新手 并且了解我可能需要以某种方式实现 EnvironmentObject 但我不确定在这种情况下如何实现 这是Trade class class Trade var teamsSelected Team init
  • 如何在Python中生成DOCX并将其保存在内存中?

    我的任务是从模板生成 DOCX 文件 然后通过 Flask 提供该文件 我用python docx 模板它只是 python docx 的包装器 允许使用 jinja 模板 最后他们建议使用 StringIO 仅将文件保存在内存中 所以我的