我正在使用Indy
和Delphi XE
开发下载管理器(应用程序使用Multithreading
尝试与服务器建立多个连接)。一切正常,但有时最终下载的文件被破坏,当我检查下载的临时文件时,我看到其中2或3个在其末尾填充为零。 (每个临时文件是每个连接的下载结果)。
文件越大,我得到的临时文件就越多。
例如,在其中一个65,536,000字节的临时文件中,只有0-34,359,426的范围是有效的,而从34,359,427到64,535,999,它充满了零。如果我删除那些零,应用程序将自动下载丢失的段和结果,如果问题不会再次发生,是健康的下载文件。
我想在临时文件的末尾摆脱那些零,而不会丢失下载速度。
P.S。我正在使用TFileStream
,我将其直接发送到TIdHTTP
并使用GET
方法下载文件。
其他信息:我处理OnWork
事件,该事件将AWorkCount
分配给公共int64
变量。每次下载文件时,下载的文件大小(那个Int64
变量)都会记录到一个文本文件中,而日志中说的是该文件已经完全下载(即使是那些零字节)。
答案 0 :(得分:1)
在请求下载范围之前,请确保服务器实际上支持下载字节范围。如果服务器不支持范围,则服务器将忽略请求的范围,而是发送整个文件。如果您还没有这样做,那么在调用TIdHTTP.Head()
之前,您应该使用TIdHTTP.Get()
发送范围支持文本。无论如何,您还需要执行此操作以检测自上次下载以来远程文件是否已被更改。任何像样的下载管理员都需要能够处理这样的事情。
另请注意,如果TIdHTTP
预先知道正在传输多少字节,它会预先分配目标TStream
的大小,然后再将数据下载到其中。这是为了在使用TFileStream
时加快传输并优化光盘I / O.因此,您应该不使用TFileStream
来访问与多个同时下载的目标相同的文件,即使它们正在写入文件的不同区域。预先分配多个TFileStream
对象可能会相互踩踏,试图将文件大小设置为不同的位置。如果您需要同时下载多个文件,则可以:
1)将每个部分下载到一个单独的文件中,并在获得所需的所有部分后,根据需要将它们复制到最终文件中。
2)使用自定义TStream
类或Indy的TIdEventStream
类来自行管理文件I / O,这样您就可以忽略TIdHTTP
的预分配尝试并确保多个文件I / O操作不会错误地重叠。