【问题标题】:Read and save part of file stream via IdHTTP通过 IdHTTP 读取和保存部分文件流
【发布时间】:2017-10-11 20:48:50
【问题描述】:

我想通过文件流从 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;

【问题讨论】:

  • 附带说明,没有理由将新创建的流的位置设置为 0。它已经是空的。
  • 没错,但我认为我需要它来实现我的目标。

标签: delphi stream indy


【解决方案1】:

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

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

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

  • 使用TIdHTTP.OnWork 事件,或使用TIdEventStream,或派生覆盖Write() 的自定义TStream,以便跟踪正在下载的字节数,因此您可以中止下载(一旦收到所需的字节数,就会引发异常,例如EAbort 通过SysUtils.Abort())。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 2018-12-25
    相关资源
    最近更新 更多