压缩 JSON 通过 CGI 在 Python 中发送

Compressing JSON sent via CGI in Python

我目前正在开发的 webApp 需要客户端请求的大型 JSON 文件,使用 Python 在服务器上构建并发送回客户端。该解决方案是通过 CGI 实现的,并且在各个方面都可以正常工作。 在这个阶段,我只是采用各种技术来最小化发送回客户端的结果 JSON objects 的大小,大约为 5-10mb(无需详细说明,这或多或少是固定的,并且不能以任何方式延迟加载)。 我们使用的主机不支持 mod_deflate 或 mod_gzip,因此虽然我们无法将 Apache 配置为使用 .htaccess 在服务器上自动创建 gzip 内容,但我认为我们仍然可以只要 Content-encoding header 设置正确,就可以在客户端接收并解码。

我想知道实现此目标的最佳方法是什么。在 Python 中压缩一些东西是微不足道的。我已经知道该怎么做,但问题是: 我如何以这种方式压缩数据,将其打印到输出流以通过 CGI 发送既压缩又可读给客户端?

文件必须根据输入数据即时创建,因此不能选择存储预制文件和预压缩文件,并且必须通过 webApp 中的 xhr 接收它们。

我最初的实验是用 gzip 和 io.stringIO 压缩 JSON 字符串,然后将其打印到输出流,导致它以 Python 的正常字节格式打印,例如: b'\n\x91\x8c\xbc\xd4\xc6\xd2\x19\x98\x14x\x0f1q!\xdc|C\xae\xe0 等等,这使请求膨胀到正常大小的两倍...

我想知道是否有人可以在这里为我指明正确的方向,告诉我如何实现这一点,如果确实可行的话。 我希望我已经正确地阐明了我的问题。 谢谢。

我猜你使用 print()(它首先将其参数转换为字符串,然后再将其发送到标准输出)或 sys.stdout(它只接受 str 对象)。

要直接在 stdout 上写入,可以使用 sys.stdout.buffer,一个支持字节对象的类文件对象:

import sys
import gzip

s = 'foo'*100

sys.stdout.buffer.write(gzip.compress(s.encode()))

给出有效的 gzip 数据:

$ python3 foo.py | gunzip
foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo

感谢 Valentin 和 Phillip 的回答! 我设法解决了这个问题,你们两个都为最终答案做出了贡献。事实证明这是多种因素的结合。 这是有效的最终代码:

    response = json.JSONEncoder().encode(loadData)  
    sys.stdout.write('Content-type: application/octet-stream\n')
    sys.stdout.write('Content-Encoding: gzip\n\n')
    sys.stdout.flush()
    sys.stdout.buffer.write(gzip.compress(response.encode()))

在切换到 sys.stdout 而不是使用 print 来打印 headers 并刷新它设法正确读取的流之后。这很好奇……总有更多东西要学。 再次感谢!