Sanic 实现 HTTP Range,解决前端视频无法拖动问题

from sanic import Sanic, response
from sanic.response import json
from sanic.response.types import HTTPResponse, JSONResponse, ResponseStream
from mimetypes import guess_type
from sanic.compat import Header, open_async, stat_async
from sanic.response import file_stream
from urllib.parse import quote, unquote
import os


app = Sanic("private-web")

def parse_range_header(range_header, file_size):
    # 解析Range参数
    start, end = range_header.split('=')[1].split('-')
    start = int(start)
    end = int(end) if end else file_size - 1

    # 确保范围在文件大小范围内
    start = min(max(start, 0), file_size - 1)
    end = min(end, file_size - 1)

    return start, end

@app.route('/video/')
async def videoRange(request, vid):
    # 网址中文转码
    vid = unquote(vid)
    # 视频路径
    file_path = f"{vid}.mp4"
    # 获取文件大小
    file_size = os.path.getsize(file_path)
    # 获取请求头Range参数
    range_header = request.headers.get("Range")
    headers = {}

    if range_header:
        # 解析Range参数
        start, end = parse_range_header(range_header, file_size)
        status = 206
        headers["Content-Range"] = f"bytes {start}-{end}/{file_size}"
        headers['Content-Length'] = str(end - start + 1)
        chunk_size: int = 4096
        mime_type = None
        mime_type = mime_type or guess_type(file_path)[0] or "text/plain"
        # 这段代码就是拿 file_stream 里的源码改的,直接使用file_stream总是报错,有大佬帮忙解释并实现下吗
        async def _streaming_fn(response):
            async with await open_async(file_path, mode="rb") as f:
                await f.seek(start)
                to_send = end - start + 1
                while to_send > 0:
                    content = await f.read(min((to_send, chunk_size)))
                    if len(content) < 1:
                        break
                    to_send -= len(content)
                    await response.write(content)

        return ResponseStream(
            streaming_fn=_streaming_fn,
            status=status,
            headers=headers,
            content_type=mime_type,
        )
    else:
        return await file_stream(file_path, headers=headers)

if __name__ == '__main__':
    app.run(host='0.0.0.0')

你可能感兴趣的:(http,音视频,python,sanic)