在Django字节范围(Byte Ranges in Django)

2019-07-18 05:07发布

是否有Django的HTTP字节范围的现有的实现? 即当客户端发送一个范围:头,我想我的Django应用程序接受并使用HTTP“206部分内容”响应回复。

我可以写从头开始,但肯定有人已经做到了这一点?

有各种不同的环节进行:

  1. 解析和健全检查范围头部
  2. 其实产生范围
  3. 在响应返回单个范围支持
  4. 用于在单个响应返回多个范围的支持,适当MIME编码

当然至少(1)和(4)有库支持地方?

Answer 1:

在两个相关的功能要求(一个是开放的,另一种是第一个副本):

  • 票务#22479 -在django.views.static.serve支持字节范围请求
  • 票务#23382 -在django.views.static.serve支持字节范围请求

这两个问题都是基于谷歌小组讨论 。

车票是在“挂起”状态 ,由于建筑的关注,并因为有关于这是否没有达成共识是真的Django的应该支持的东西。 这主要是因为网络服务器能够字节服务的。

如果你仍然有兴趣在实现,有送实施特殊的一个尚未审查的补丁RangedFileReader类返回使用大块的响应StreamingHttpResponse ,有分析和健全检查HTTP_RANGE头:

  • 从HTTP范围标头添加支持

你可以尝试一下叉或使用该解决方案作为自己的基地。

仅供参考,有一个又一个尝试制作这里 -这还没有结束,但可以审查有用。


要分析Range头,请参阅:

  • werkzeugparse_range_header()
  • parse_range_header()从上面PR所提到的
  • httpheaderparse_range_header()也参见使用HTTP范围请求 )


Answer 2:

下面是一些基本的中间件代码,应该Django的1.8+工作。 它只能处理一个单一的范围内,但仅此而已,我个人需要。

import os

try:
    from django.utils.deprecation import MiddlewareMixin
except ImportError:  # django < 1.10
    MiddlewareMixin = object


class RangesMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        if response.status_code != 200 or not hasattr(response, 'file_to_stream'):
            return response
        http_range = request.META.get('HTTP_RANGE')
        if not (http_range and http_range.startswith('bytes=') and http_range.count('-') == 1):
            return response
        if_range = request.META.get('HTTP_IF_RANGE')
        if if_range and if_range != response.get('Last-Modified') and if_range != response.get('ETag'):
            return response
        f = response.file_to_stream
        statobj = os.fstat(f.fileno())
        start, end = http_range.split('=')[1].split('-')
        if not start:  # requesting the last N bytes
            start = max(0, statobj.st_size - int(end))
            end = ''
        start, end = int(start or 0), int(end or statobj.st_size - 1)
        assert 0 <= start < statobj.st_size, (start, statobj.st_size)
        end = min(end, statobj.st_size - 1)
        f.seek(start)
        old_read = f.read
        f.read = lambda n: old_read(min(n, end + 1 - f.tell()))
        response.status_code = 206
        response['Content-Length'] = end + 1 - start
        response['Content-Range'] = 'bytes %d-%d/%d' % (start, end, statobj.st_size)
        return response

它安装在settings.py像这样:

MIDDLEWARE_CLASSES = [
    'path.to.RangesMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
]


Answer 3:

有关内容范围三个approches

选择由您的具体情况适当的一个。

1.支持所有的动态视图和静态文件

该白噪声提供了一个中间件支持全局设置。

2.仅支持静态文件

Nginx的可以支持静态和媒体文件。

查看更多详情与uWSGI和nginx的设置Django和Web服务器 。 如果一些看法需要重定向到静态或媒体文件,看到的计算器答案 。

3.仅支持特定的动态视图

Django的远程响应支持与内容范围的响应。 使用你想要的每一个意见的回应。 意见大多是专为媒体API,如语音合成,视频发生器。


声明:我的Django的贡献者远程响应。 但我认为使用白噪声是最容易维护。



文章来源: Byte Ranges in Django