压缩在Python中通过CGI发送的JSON

时间:2015-04-10 04:43:53

标签: python json xmlhttprequest cgi gzip

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

我想知道的是,实现这一目标的最佳途径是什么。在Python中使用Gzipping是微不足道的。我已经知道如何做到这一点,但问题是: 如何以这种方式压缩数据,将其打印到输出流以通过CGI发送将被压缩,并且可以被客户端读取?

必须根据输入数据动态创建文件,因此存储预制文件和预先存档文件不是一种选择,必须通过webApp中的xhr接收它们。

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

我想知道是否有人可以指出我在这方面的正确方向,如果确实可能的话,我将如何实现这一目标。 我希望我能正确地表达我的问题。 谢谢。

2 个答案:

答案 0 :(得分:1)

我猜你使用print()(在将其发送到stdout之前首先将其参数转换为字符串)或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

答案 1 :(得分:0)

感谢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打印标题,并刷新它设法正确读取的流。这很奇怪......总是需要学习的东西。 再次感谢!