1

Via a simple Python 3 CGI App, I'm wanting to generate an XLSX file (using OpenPYXL), save it in memory, and force a download of the file to a browser. The test code that I'm using is as follows:

#!/usr/bin/env python

import os,sys
import io
import openpyxl

print("Content-Type: application/octet-stream; name = test.xlsx")
print("Content-Disposition: attachment; filename = test.xlsx\n")

wb = openpyxl.Workbook()
ws = wb.active
ws['A1'] = "hello"
ws['A2'] = "there!"

output = io.BytesIO()
wb.save(output)
print(output.getvalue())

The resulting file on disk starts as follows:

b'PK\x03\x04\x14\x00\x00\x00\x08\x00Tu\xd0T\x07AMb....

XLS files are ZIP compressed - and this looks like a segment of a compressed file. The problem is that I'm not sure how to write it out as a binary file that Excel will be able to open.

I have tried:

print(output.getvalue().decode('utf-8'))

The problem is that I end up with:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 10: invalid continuation byte

because this isn't a UTF-8 file - XLSX documents are compressed files.

Using other codecs like raw_unicode_escape and unicode_escape look closer to the expected format - but they are still corrupt when trying to open it in Excel (or extract via unzip).

Can anyone point me in the right direction, as to how to create a file that can be correctly downloaded and opened via Excel.

Patrick Rynhart
  • 485
  • 4
  • 11
  • 1
    https://stackoverflow.com/questions/18339745/how-to-deploy-zip-files-or-other-binaries-trough-cgi-in-python – GordonAitchJay Jun 16 '22 at 03:59
  • 1
    @GordonAitchJay: Thanks for the hint. Looks like the crux is "You should not use print() for binary data in any case; all you get is b'...' byte literal syntax. The sys.stdout.buffer object is the underlying binary I/O buffer, copy binary data directly to that." – Patrick Rynhart Jun 16 '22 at 04:48
  • 1
    Yeah that makes sense. `print` writes the _representation_ of the `bytes` variable to stdout, instead of the raw bytes themselves. – GordonAitchJay Jun 16 '22 at 08:06
  • Thank you @GordonAitchJay. Got it working now thanks to the tip . Much appreciated – Patrick Rynhart Jun 17 '22 at 09:07

0 Answers0