通过 IdHTTP 读取和保存部分文件流
Read and save part of file stream via IdHTTP
我想通过文件流从 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;
如果 HTTP 服务器支持所需 URL 的字节范围(通过存在的 Range
request header), you can request just the specific bytes you want, and that is all the server will send. You can use the TIdHTTP.Request.Range
property for that when calling TIdHTTP.Get()
. To discover if the server supports byte ranges, use TIdHTTP.Head()
first to get the URL's headers, and then check if there is an Accept-Ranges: bytes
header(参见 TIdHTTP.Response.AcceptRanges
属性)。
如果服务器不支持字节范围,您将不得不继续使用您当前拥有的代码,只需对其进行一些更改:
不是调用 fs.SaveToFile()
,而是创建一个单独的 TFileStream
object 并将 TMemoryStream
传递给它的 CopyFrom()
方法,即您可以准确指定要保存多少字节的方式。
使用 TIdHTTP.OnWork
事件,或使用 TIdEventStream
,或派生覆盖 Write()
的自定义 TStream
,以便跟踪正在下载多少字节,因此您可以在收到所需字节数后中止下载(通过引发异常,例如 EAbort
通过 SysUtils.Abort()
)。
当然,这两种方法都是面向字节而不是面向行。如果你需要 line-oriented,特别是如果行是可变长度的,那么你将不得不使用上面的第二种方法,使用 TIdEventStream
或自定义 TStream
,这样你就可以实现行解析逻辑并仅将完整行保存到文件中,然后在收到所需行数后中止。
我想通过文件流从 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;
如果 HTTP 服务器支持所需 URL 的字节范围(通过存在的 Range
request header), you can request just the specific bytes you want, and that is all the server will send. You can use the TIdHTTP.Request.Range
property for that when calling TIdHTTP.Get()
. To discover if the server supports byte ranges, use TIdHTTP.Head()
first to get the URL's headers, and then check if there is an Accept-Ranges: bytes
header(参见 TIdHTTP.Response.AcceptRanges
属性)。
如果服务器不支持字节范围,您将不得不继续使用您当前拥有的代码,只需对其进行一些更改:
不是调用
fs.SaveToFile()
,而是创建一个单独的TFileStream
object 并将TMemoryStream
传递给它的CopyFrom()
方法,即您可以准确指定要保存多少字节的方式。使用
TIdHTTP.OnWork
事件,或使用TIdEventStream
,或派生覆盖Write()
的自定义TStream
,以便跟踪正在下载多少字节,因此您可以在收到所需字节数后中止下载(通过引发异常,例如EAbort
通过SysUtils.Abort()
)。
当然,这两种方法都是面向字节而不是面向行。如果你需要 line-oriented,特别是如果行是可变长度的,那么你将不得不使用上面的第二种方法,使用 TIdEventStream
或自定义 TStream
,这样你就可以实现行解析逻辑并仅将完整行保存到文件中,然后在收到所需行数后中止。