import os
from typing import Tuple
from jivago.wsgi.request.request import Request
from jivago.wsgi.request.response import Response
[docs]class PartialContentHandler(object):
[docs] def handle_partial_content_request(self, request: Request, filepath: str, *, max_block_size: int = 2000000) -> Response:
if request.headers['Range']:
total_filesize = os.path.getsize(filepath)
start, end = self._parse_range_string(request.headers['Range'], max_block_size, total_filesize)
return Response(206, {"Content-Type": "application/octet-stream", "Accept-Ranges": "bytes",
"Content-Range": f"bytes {start}-{end - 1}/{total_filesize}"}, self._read_partial_file(filepath, start, end))
return Response(200, {"Content-Type": "application/octet-stream"}, self._read_whole_file(filepath))
def _parse_range_string(self, range_string: str, default_block_size: int, file_end_offset: int) -> Tuple[int, int]:
start = int(range_string.split("=")[1].split("-")[0])
end_string = range_string.split("-")[1]
end = int(end_string) if end_string != '' else start + default_block_size
if end > file_end_offset:
end = file_end_offset
return start, end
def _read_partial_file(self, filepath: str, start: int, end: int) -> bytes:
with open(filepath, 'rb') as f:
f.seek(start)
return f.read(end - start)
def _read_whole_file(self, filepath: str) -> bytes:
with open(filepath, 'rb') as f:
return f.read()