【问题标题】:TIdHTTP filestream incomplete downloadsTIdHTTP 文件流下载不完整
【发布时间】:2022-01-10 16:24:45
【问题描述】:

基本上,我正在使用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;

我的问题是当/如果用户在下载过程中关闭/杀死程序。该文件不是显示文件大小小于应有的大小,而是已完成下载的大小。这是为什么呢?

我使用文件大小作为快速检查以查看下载是否成功,因此具有正确的大小,但错误的内容会导致其他错误。我不想对每个文件进行哈希校验和,因为它们有很多,而且 MD5 检查需要一些较大的多 GB 大小的文件。

如果下载因任何原因中断,是否有办法使目标文件变小?除非所有下载都正常完成,否则有什么方法可以不将流扩展到完整大小?

【问题讨论】:

    标签: delphi indy idhttp


    【解决方案1】:

    如果文件大小在下载开始时已知,即在 HTTP Content-Length 标头中,则 TIdHTTP(更具体地说,TIdIOHandler.ReadStream())将流预分配为完整大小以增加 I/ O 下载期间的性能。

    如果下载(而不是应用程序)过早终止,ReadStream() 具有减小流大小以匹配实际下载字节数的逻辑。因此,在这种情况下,除非下载完成,否则文件不应保持完整大小。

    但是,如果用户终止了应用程序,那么该代码将不会运行,所以是的,文件将保留在预先分配的大小。 Indy 目前没有禁用该预分配逻辑的选项。实际上,代码中有一个 TODO 项。

    与此同时,有一个简单的解决方法 - 您可以从 TFileStream 派生自定义类并覆盖其虚拟 SetSize() 方法(Size 属性的设置器)以不执行任何操作。 Indy 不会验证请求的大小是否已实际应用。只要流的 SizePosition 属性 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 2012-05-23
      相关资源
      最近更新 更多