You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TIdHttpServer响应HTTP GET发送文件片段,多连接分段下载遇阻

如何让Web服务器正确支持多连接分段下载?

我正在开发一款小型Web服务器,希望支持下载管理器通过多连接同时分段下载大文件。目前已经能通过ARequestInfo.Ranges属性检测到下载管理器的分段下载请求,还编写了自定义TFileFragmentStream类,以TStream子类的形式提供指定范围的文件片段。但下载管理器似乎不认可服务器支持该功能,仍然只用单连接下载——不过我能看到它发起了分段请求,推测是响应的设置没满足要求。

我当前的初始实现代码如下:

PROCEDURE SendPartialFile(Response : TIdHttpResponseInfo ; CONST N : TFileName ; RangeStart,RangeEnd : Int64);
BEGIN      
  Response.ContentType:='application/octet-stream';
  Response.ContentDisposition:='attachment; filename="'+ExrractFileName(N)+'"';
  Response.ContentLength:=SUCC(RangeEnd-RangeStart);
  Response.ContentStream:=TFileFragmentStream.Create(N,RangeStart,ContentLength)
  Response.FreeContentStream:=TRUE
END;

请问还需要设置响应的哪些属性?


最终更新代码:

ContentDisposition:='attachment; filename="'+N.NameOnly+'"';
VAR S:=TIdHTTPRangeStream.Create(TFileStream.Create(N,fmOpenRead OR fmShareDenyNone),RangeStart,RangeEnd);
ContentStream:=S;
ResponseNo:=S.ResponseCode;
ContentRangeStart:=S.RangeStart;
ContentRangeEnd:=S.RangeEnd;
ContentText:='';
ContentRangeInstanceLength:=S.SourceStream.Size;
OutputDebugString('Sending File Fragment: '+ContentType+' ['+IntToStr(ContentRangeStart)+'-'+IntToStr(ContentRangeEnd)+'] ('+IntToStr(ContentLength)+' bytes) "'+ContentDisposition+'" ResponseNo='+IntToStr(ResponseNo));
FreeContentStream:=TRUE;

日志信息如下:

Sending Full File: video/mp4 XX.mp4 (6573584385 bytes)
Sending File Fragment: video/mp4 [233600-6573584384] (6573350785 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [3286914832-6573584384] (3286669553 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [4930249645-6573584384] (1643334740 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [1655659767-3286914895] (1631255129 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [4108582275-4930249708] (821667434 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [5751917052-6573584384] (821667333 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [2471287336-3286914895] (815627560 bytes) "attachment; filename="XX.mp4"" ResponseNo=206
Sending File Fragment: video/mp4 [855370091-1655659830] (800289740 bytes) "attachment; filename="XX.mp4"" ResponseNo=206

完整文件的处理代码如下:

ContentType:='application/octet-stream'
ContentDisposition:='attachment; filename="'+ExtractFileName(FileName)+'"'
ContentStream:=TFileStream.Create(FileName,fmOpenRead OR fmShareDenyNone)
FreeContentStream:=TRUE
ResponseNo:=200

问题分析与解决要点

  1. 设置正确的响应状态码
    分段下载请求的响应必须返回206 Partial Content状态码,而非默认的200。初始代码未设置Response.ResponseNo,客户端会误认为服务器不支持范围请求,因此不会启用多连接下载。

  2. 完善Content-Range相关属性
    除ContentLength外,还需明确告知客户端当前片段的范围和文件总大小:

    • ContentRangeStart:当前片段的起始字节位置
    • ContentRangeEnd:当前片段的结束字节位置
    • ContentRangeInstanceLength:整个文件的总字节数
      这些属性会组装成Content-Range响应头,是客户端识别分段内容的核心依据。
  3. 主动声明支持范围请求
    在处理完整文件请求(响应码200)时,需添加Accept-Ranges: bytes响应头,主动告知客户端服务器支持分段下载,这样下载管理器才会尝试发起多连接分段请求。可在完整文件处理代码中补充:

    Response.AcceptRanges := 'bytes';
    
  4. 修复代码拼写错误
    初始代码中的ExrractFileName是拼写错误,应改为ExtractFileName,否则会导致文件名解析错误,影响下载后的文件名正确性。

从你提供的最终代码和日志来看,改用TIdHTTPRangeStream后已自动处理了响应码和ContentRange相关属性,日志中也显示多个206响应的分段请求,说明服务器已正确支持多连接分段下载。


内容的提问来源于stack exchange,提问作者HeartWare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:50:03