如何在TIdHTTPServer中处理GET请求实现浏览器视频拖拽定位?
实现支持进度拖拽的MP4 HTTP服务器(基于IdHTTPServer)
问题描述
使用Delphi的IdHTTPServer实现了简易HTTP服务器,可完整播放MP4视频,但无法支持浏览器中的进度跳转功能。当前核心代码如下:
... AResponseInfo.ContentStream := TFileStream.Create('MyVideo.mp4', fmOpenRead or fmShareCompat); ...
解决方案:支持HTTP Range请求
浏览器调整播放进度时,会向服务器发送包含Range字段的请求,要求获取文件的指定片段。服务器需要解析该请求并返回对应的文件部分,同时设置正确的响应头。
具体实现逻辑
- 检查请求头中是否存在
Range字段 - 解析
Range格式,提取起始偏移量和结束偏移量 - 修正超出文件范围的偏移值,计算要发送的内容长度
- 设置响应状态码为
206 Partial Content,并填充Content-Range、Accept-Ranges等关键响应头 - 打开文件流,定位到起始偏移位置,读取指定长度的内容返回
完整代码示例
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var VideoPath: string; FileSize: Int64; StartPos, EndPos, SendSize: Int64; RangeStr: string; FileStream: TFileStream; ContentStream: TMemoryStream; begin VideoPath := 'MyVideo.mp4'; if not FileExists(VideoPath) then begin AResponseInfo.ResponseNo := 404; Exit; end; FileSize := TFile.GetSize(VideoPath); AResponseInfo.AcceptRanges := 'bytes'; AResponseInfo.ContentType := 'video/mp4'; // 处理Range分段请求 RangeStr := ARequestInfo.Ranges.Text; if RangeStr <> '' then begin if Pos('bytes=', RangeStr) = 1 then begin Delete(RangeStr, 1, 6); // 解析起始偏移 StartPos := StrToIntDef(Copy(RangeStr, 1, Pos('-', RangeStr)-1), 0); // 解析结束偏移,默认到文件末尾 EndPos := StrToIntDef(Copy(RangeStr, Pos('-', RangeStr)+1, MaxInt), FileSize-1); // 校验偏移合法性 if StartPos >= FileSize then begin AResponseInfo.ResponseNo := 416; // 请求范围无效 AResponseInfo.ContentText := 'Requested range not satisfiable'; Exit; end; if EndPos >= FileSize then EndPos := FileSize - 1; SendSize := EndPos - StartPos + 1; AResponseInfo.ResponseNo := 206; // 返回部分内容 AResponseInfo.ContentRange := Format('bytes %d-%d/%d', [StartPos, EndPos, FileSize]); AResponseInfo.ContentLength := SendSize; // 读取指定范围的文件内容 FileStream := TFileStream.Create(VideoPath, fmOpenRead or fmShareCompat); try FileStream.Position := StartPos; ContentStream := TMemoryStream.Create; try ContentStream.CopyFrom(FileStream, SendSize); AResponseInfo.ContentStream := ContentStream; except ContentStream.Free; raise; end; finally FileStream.Free; end; end; end else begin // 无Range请求,返回完整文件 AResponseInfo.ResponseNo := 200; AResponseInfo.ContentLength := FileSize; AResponseInfo.ContentStream := TFileStream.Create(VideoPath, fmOpenRead or fmShareCompat); end; end;
关键说明
Accept-Ranges: bytes:告知客户端服务器支持字节范围请求206 Partial Content:明确返回的是文件的部分内容Content-Range:指定返回内容的字节区间和文件总大小,帮助浏览器定位播放进度- 必须处理超出文件范围的请求,返回416状态码避免客户端报错
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

