title: How to generate a DOCX in Python and save it in memory?
body: <p>I have a task of generating a DOCX file from a template and then serving it via Flask. I use <a href="http://docxtpl.readthedocs.io/en/latest/" rel="noreferrer">python-docx-templates</a> which is simply a wrapper around python-docx allowing for use of jinja templates.</p>
  
  <p>In the end they suggest using StringIO to save file only in memory, so this is how my code looks like:</p>
  
  <pre><code>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')
  </code></pre>
  
  <p>On saving it throws an error <code>TypeError: string argument expected, got 'bytes'</code>. After googling it, I found <a href="https://stackoverflow.com/questions/32075135/python-3-in-memory-zipfile-error-string-argument-expected-got-bytes">this answer</a> which says that <code>ZipFile</code> expects BytesIO. However, when I substituted StringIO with BytesIO, it only returned an empty file, so it doesn't throw any error, but definitely doesn't save the file.</p>
  
  <p>What exactly would work in this case? If something is entirely wrong here, how in general could this work?</p>
  
  <p>Thank you!</p>
  
  <p>UPD: Here's the exception with full trace to the <code>save</code> function call:</p>
  
  <pre><code>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'
  </code></pre>