42

我正在尝试在 Django 中提供文本/html 页面的 gzip 压缩版本,但 Firefox 告诉我存在内容编码错误。

笔记:

  • 我意识到这不是最佳实践,我很可能会使用 mod_gzip。这只是一个学习练习,以了解正在发生的事情。
  • 我知道 Django gzip 中间件——它有二进制文件的问题。

这是我的代码:

rendered_page =  zlib.compress(template.render(context).encode('utf-8'))

response = HttpResponse(rendered_page)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = len(rendered_page)
return response

我在这里错过了什么吗?内容长度是否可能错误?我还缺少其他标题吗?

谢谢。

4

6 回答 6

96

你也可以简单地使用Django 的 GZip Middleware

通过在 settings.py 中启用中间件添加:

MIDDLEWARE_CLASSES = (
    django.middleware.gzip.GZipMiddleware,
    ...
)

或者在您返回特定响应之前执行此操作。在您的 views.py 中,dec 将是某个 url 的处理程序

from django.middleware.gzip import GZipMiddleware

gzip_middleware = GZipMiddleware()

 def dec(request, *args, **kwargs):
        response = func(request, *args, **kwargs)
        return gzip_middleware.process_response(request, response)
        return dec

注意:在使用 GZip 中间件之前,您应该确定自己没有受到旁道攻击。

警告

安全研究人员最近透露,当在网站上使用压缩技术(包括 GZipMiddleware)时,该网站可能会受到许多可能的攻击。在您的站点上使用 GZipMiddleware 之前,您应该非常仔细地考虑您是否会受到这些攻击。如果您对自己是否受到影响有任何疑问,您应该避免使用 GZipMiddleware。有关更多详细信息,请参阅 BREACH 论文 (PDF) 和 bypassattack.com。

还:

Django 1.10 中的更改:在旧版本中,Django 的 CSRF 保护机制在使用压缩时容易受到 BREACH 攻击。现在情况已不再如此,但您仍应注意不要以这种方式泄露自己的秘密。

于 2009-12-08T03:28:26.820 回答
28

如果您正在压缩单个页面,而不是所有页面,则可以使用gzip_page装饰器而不是 GzipMiddleware。

from django.views.decorators.gzip import gzip_page

@gzip_page
def viewFunc(request):
  return HttpResponse("hello"*100)

参考这里:https ://docs.djangoproject.com/en/1.4/topics/http/decorators/#module-django.views.decorators.gzip

于 2013-02-11T22:00:40.110 回答
26

zlib对于这个目的来说有点太低级了。以下是 GZip 中间件本身的工作方式(参见django.utils.text.py中的 compress_string ):

import cStringIO, gzip
zbuf = cStringIO.StringIO()
zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
zfile.write(template.render(context).encode('utf-8'))
zfile.close()

compressed_content = zbuf.getvalue()
response = HttpResponse(compressed_content)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = str(len(compressed_content))
return response

GZip 使用 zlib,但 zlib 自身生成的内容对于将“gzip”视为内容编码的浏览器来说编码不正确。希望有帮助!

于 2009-06-05T19:57:02.320 回答
1

为了其他人发现这个问题并且谁正在使用 nginx,这个 SO 对我有用:

https://stackoverflow.com/a/41820704/4533488

基本上在 /etc/nginx/nginx.conf 文件中打开 gzip 为我完成了所有的压缩处理。在客户端,大多数现代浏览器在接收数据时会自动处理提取(解压缩)数据——太好了!

这是 nginx.conf 文件设置:

    http {

        #... other settings ...#

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    }
于 2017-01-24T05:39:55.800 回答
1

如果您需要它用于单个页面并且您正在使用基于类的视图,请使用以下命令:

gzip_middleware = GZipMiddleware()

class GZipMixin(object):

    def dispatch(self, request, *args, **kwargs):
        response = super(GZipMixin, self).dispatch(request, *args, **kwargs)
        return gzip_middleware.process_response(request, response)

然后在您的实际视图中:

class MyView(GZipMixin, View):
    def get(self, request, *args, **kwargs):
         #return your response
于 2018-04-05T06:38:11.917 回答
1

如果使用 压缩数据zlib,则必须设置Content-Encodingdeflate,而不是gzip

rendered_page =  zlib.compress(template.render(context).encode('utf-8'))

response = HttpResponse(rendered_page)
response['Content-Encoding'] = 'deflate'
response['Content-Length'] = len(rendered_page)
return response

内容编码

(...)

放气

使用 zlib 结构(在 RFC 1950 中定义)和 deflate 压缩算法(在 RFC 1951 中定义)。

于 2019-02-15T12:38:30.377 回答