Repository navigation
v1.1
在 v1.0 版本中:
代码当前仅处理了范围请求的起始字节,没有处理可能指定的结束字节。对于形如Range: bytes=0-499的请求,服务器会发送从0字节开始到文件末尾的全部内容,而不是仅发送前500字节。这会导致下载可能出现如下图中的问题。

因此,处理结束字节的逻辑需要被添加。
在 v1.1 版本中:
正确处理了Range请求中可能指定的结束字节。这在以下代码段中得到体现:
range_value = range_header.strip().split('=')[1]
start_byte, end_byte = map(lambda x: int(x) if x else None, range_value.split('-'))这里,range_value.split('-')将Range头部的值(例如bytes=0-499)分割成起始和结束字节(0和499)。如果请求中未指定结束字节(即请求头为bytes=0-这样的形式),end_byte将被设置为None。随后的代码检查了end_byte的值,并相应地处理:
# 如果没有指定结束字节,使用文件的最后一个字节
if end_byte is None or end_byte >= file_size:
end_byte = file_size - 1如果end_byte是None或者大于等于文件的大小,它会被设置为文件的最后一个字节的索引(file_size - 1)。这确保了即使在请求中只指定了起始字节,服务器也能正确地返回从起始字节到文件末尾的内容。
接着,在计算响应头Content-Range和确定发送的数据量时,代码使用了这个经过处理的end_byte值:
self.send_header("Content-Range", f"bytes {start_byte}-{end_byte}/{file_size}")
self.send_header("Content-Length", str(end_byte - start_byte + 1))这里,Content-Range响应头明确指出了实际返回的数据范围,而Content-Length响应头表示这个范围内的字节数。最后,通过读取并发送指定范围内的数据,确保了只有请求的部分内容被发送给客户端。
while remaining_bytes > 0:
block_size = min(65536, remaining_bytes) # 选择较小的值避免过大的内存使用
data = f.read(block_size)
if not data:
break # 文件读取完毕
self.wfile.write(data) # 发送数据块
remaining_bytes -= len(data) # 更新剩余字节数通过这种方式,代码正确处理了形如Range: bytes=0-499的请求,只返回请求范围内的数据,而不是从指定的起始字节到文件末尾的全部内容。这样,无论客户端请求文件的哪一部分,服务器都能正确、高效地返回相应的内容。