通过IdHTTP读取并保存部分文件流

Pet*_*mch 3 delphi indy stream

我想通过文件流从HTTP服务器下载文件,只读取(并保存到文件)前几行,比如100.读完前100行后,文件流必须结束:所以我不想下载或阅读整个文件.

下面你可以找到我到目前为止所拥有的.该网站只是一个例子.有人能引导我朝正确的方向发展吗?

const
  myURL = https://graphical.weather.gov/xml/DWMLgen/schema/latest_DWML.txt
var
  fs: TMemoryStream;
  http: TIdHTTP; 
begin
  fs := TMemoryStream.Create;
  http := TIdHTTP.Create(nil);
  try
    fs.Position := 0;
    http.Get(myURL, fs);
    fs.SaveToFile('test.xml');
  finally
    fs.Free;
    http.free
  end;
end;
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 10

如果HTTP服务器支持所需URL的字节范围(通过Range请求标头),则可以只请求所需的特定字节,这是服务器将发送的全部内容.您可以TIdHTTP.Request.Range在通话时使用该属性TIdHTTP.Get().要发现服务器是否支持字节范围,TIdHTTP.Head()请先使用以获取URL的标头,然后检查是否存在Accept-Ranges: bytes标头(请参阅TIdHTTP.Response.AcceptRanges属性).

如果服务器不支持字节范围,则必须继续使用当前的代码,只需对其进行一些更改:

  • 而不是调用fs.SaveToFile(),创建一个单独的TFileStream对象并传递TMemoryStream给它的CopyFrom()方法,这样你就可以确切地指定要保存的字节数.

  • 使用TIdHTTP.OnWork事件,或者使用TIdEventStream或者派生一个TStream覆盖的自定义,Write()以便跟踪正在下载的字节数,这样你就可以在所需的字节数有一个字节后中止下载(通过引发异常,如EAbortvia SysUtils.Abort())已收到.

当然,任何一种方法都是面向字节的而不是面向行的.如果你需要面向行,特别是如果行是可变长度,那么你将不得不使用上面的第二种方法,使用TIdEventStream或自定义TStream,这样你就可以实现行解析逻辑并只保存完整的行到你的文件,然后在收到所需行数后再中止.