Байт-диапазоны в Django
Существует ли существующая реализация диапазонов байтов HTTP в Django? То есть когда клиент отправляет заголовок Range: я хочу, чтобы приложение Django принимало это и отвечало с ответом HTTP "206 Partial Content".
Я мог писать что-то с нуля, но, конечно же, кто-то уже это сделал?
Здесь есть несколько частей:
- Анализ и проверка работоспособности заголовка диапазона
- Фактически, создавая диапазоны
- Поддержка возврата одного диапазона в ответе
- Поддержка возврата нескольких диапазонов в одном ответе, соответствующим MIME-кодированным
По крайней мере, (1) и (4) имеют библиотечную поддержку где-нибудь?
Ответы
Ответ 1
Это два соответствующих запроса функций (один открыт, другой - дубликат первого):
Оба вопроса основаны на обсуждении Google Group.
Билет находится в "зависающем" состоянии из-за архитектурных проблем, и поскольку нет консенсуса относительно того, действительно ли это должно поддерживать Django. В основном потому, что веб-серверы могут обслуживать байты.
Если вы все еще заинтересованы в реализации, есть еще не рассмотренный исправленный патч, реализующий специальный класс RangedFileReader
для возврата ответа в кусках с помощью StreamingHttpResponse
, выполняется проверка синтаксического анализа и проверки работоспособности для HTTP_RANGE
заголовок:
Вы можете опробовать вилку или использовать ее в качестве базы.
FYI, была сделана еще одна попытка здесь - она не была закончена, но может быть полезна для просмотра.
Чтобы проанализировать заголовок Range
, см.
Ответ 2
Вот некоторый базовый код промежуточного кода, который должен работать для Django 1.8+. Он обрабатывает только один диапазон, но все, что мне лично нужно.
import os
class RangesMiddleware(object):
def process_response(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
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',
]
Ответ 3
Три утверждения о диапазоне содержимого
Выберите правильную по своей ситуации.
1. Поддержка всех динамических представлений и статических файлов
WhiteNoise предоставляет промежуточное программное обеспечение для поддержки глобальных настроек.
2. Поддержка только статических файлов
Nginx может поддерживать статические и мультимедийные файлы.
Подробнее о Настройка Django и вашего веб-сервера с помощью uWSGI и nginx. Если некоторые представления нуждаются в перенаправлении на статические или мультимедийные файлы, см. fooobar.com/info/260786/....
3. Поддержка только определенных динамических представлений
Django Ranged Response поддерживает ответы с диапазоном содержимого. Используйте этот ответ для всех просмотров, которые вы хотели. Представления в основном предназначены для медиа API, таких как синтез речи, видеогенераторы.
объявить: я являюсь вкладчиком Django Ranged Response. Но я думаю, что использование WhiteNoise проще всего поддерживать.