TIdHTTP 文件流下载不完整
TIdHTTP filestream incomplete downloads
我正在使用 TIdHTTP.Get()
将(可能很大的)文件检索到 TFileStream
,基本上;
filestream := TFileStream.Create(destination, fmCreate);
http.HandleRedirects := True;
try
http.Get(url, filestream);
except
on E: Exception do Memo.Lines.Add(E.Message);
end;
filestream.Free;
我的问题是 when/if 用户 closes/kills 下载过程中的程序。文件大小不是显示为小于应有的大小,而是已完成下载的大小。这是为什么?
我使用文件大小来快速检查下载是否成功,因此大小合适,但错误的内容会导致其他错误。我不想对每个文件进行哈希校验和,因为它们有很多,而且 MD5 检查需要一段时间才能处理更大的多 GB 大小的文件。
如果下载因任何原因中断,是否有办法减小目标文件的大小?除非所有下载都已完成,否则不将流扩展到完整大小的一些方法好吗?
如果文件大小在下载开始时已知,即在 HTTP Content-Length
header 中,则 TIdHTTP
(更具体地说,TIdIOHandler.ReadStream()
)pre-allocates 流到完整大小以提高 I/O 下载期间的性能。
如果下载(不是应用程序)过早终止,ReadStream()
有逻辑来减少流的大小以匹配实际下载的字节数。因此,在这种情况下,除非下载完成,否则不应保留完整大小的文件。
但是,如果用户终止应用程序,则该代码不会 运行,所以是的,文件将保留 pre-allocated 大小。目前 Indy 中没有选项可以禁用 pre-allocate 逻辑。实际上,代码中有一个 TODO 项目。
同时,有一个简单的解决方法 - 您可以从 TFileStream
派生自定义 class 并覆盖其虚拟 SetSize()
方法(Size
属性's setter) 什么也不做。 Indy 不验证实际应用了请求的大小。只要流的 Size
和 Position
属性 getter 正常工作,你应该没问题。
type
TFileStreamNoPreSize = class(TFileStream)
protected
procedure SetSize(const NewSize: Int64); override;
end;
procedure TFileStreamNoPreSize.SetSize(const NewSize: Int64);
begin
// do nothing...
end;
...
filestream := TFileStreamNoPreSize.Create(destination, fmCreate);
我正在使用 TIdHTTP.Get()
将(可能很大的)文件检索到 TFileStream
,基本上;
filestream := TFileStream.Create(destination, fmCreate);
http.HandleRedirects := True;
try
http.Get(url, filestream);
except
on E: Exception do Memo.Lines.Add(E.Message);
end;
filestream.Free;
我的问题是 when/if 用户 closes/kills 下载过程中的程序。文件大小不是显示为小于应有的大小,而是已完成下载的大小。这是为什么?
我使用文件大小来快速检查下载是否成功,因此大小合适,但错误的内容会导致其他错误。我不想对每个文件进行哈希校验和,因为它们有很多,而且 MD5 检查需要一段时间才能处理更大的多 GB 大小的文件。
如果下载因任何原因中断,是否有办法减小目标文件的大小?除非所有下载都已完成,否则不将流扩展到完整大小的一些方法好吗?
如果文件大小在下载开始时已知,即在 HTTP Content-Length
header 中,则 TIdHTTP
(更具体地说,TIdIOHandler.ReadStream()
)pre-allocates 流到完整大小以提高 I/O 下载期间的性能。
如果下载(不是应用程序)过早终止,ReadStream()
有逻辑来减少流的大小以匹配实际下载的字节数。因此,在这种情况下,除非下载完成,否则不应保留完整大小的文件。
但是,如果用户终止应用程序,则该代码不会 运行,所以是的,文件将保留 pre-allocated 大小。目前 Indy 中没有选项可以禁用 pre-allocate 逻辑。实际上,代码中有一个 TODO 项目。
同时,有一个简单的解决方法 - 您可以从 TFileStream
派生自定义 class 并覆盖其虚拟 SetSize()
方法(Size
属性's setter) 什么也不做。 Indy 不验证实际应用了请求的大小。只要流的 Size
和 Position
属性 getter 正常工作,你应该没问题。
type
TFileStreamNoPreSize = class(TFileStream)
protected
procedure SetSize(const NewSize: Int64); override;
end;
procedure TFileStreamNoPreSize.SetSize(const NewSize: Int64);
begin
// do nothing...
end;
...
filestream := TFileStreamNoPreSize.Create(destination, fmCreate);