通过文件流取消保存文件的适当方法?

Appropriate way to cancel saving file via file stream?

我正在编写的一个工具负责在数小时内下载数千个图像文件。最初,使用 TIdHTTP,我会将文件 Get 转换为 TMemoryStream,然后将其保存到文件,只要没有例外。为了提高速度,我把TMemoryStream改成了TFileStream

但是,现在如果没有找到资源,或者任何导致没有实际文件的异常,它仍然会保存一个空文件。

完全可以理解,因为我只是在下载之前创建了一个文件流...

FileStream:= TFileStream.Create(FileName, fmCreate);
try
  Web.Get(AURL, FileStream);
finally
  FileStream.Free;
end;

我知道如果出现异常我可以简单地删除文件。但这似乎太草率了。我确定有更合适的方法来中止这种情况。

如果出现异常,我应该如何做到不保存文件,同时不改变性能(如果可能的话)?

How should I make this to not save a file if there was an exception, while not altering the performance (if at all possible)?

这通常是不可能的。错误和失败可能发生在任何步骤,包括下载的中途。一旦理解了这一点,您就必须接受可以部分下载然后放弃该文件的事实。什么时候存储在哪里?

显而易见的选择是内存和文件。您不想存储到内存中,而是留给文件。

这会将您带回到当前的解决方案。

I know I could simply delete the file if there was an exception.

这是正确的做法。这有几个变体。例如,您可能会下载到一个临时文件,该文件创建时带有标志以安排在关闭时将其删除。只有下载完成后,您才会复制到真正的目的地。这是浏览器采用的方法。但基本思想是下载到文件并通过整理处理任何故障。

如果服务器支持,您可以考虑使用 HTTP 范围请求,而不是一次下载整个图像。然后您可以将文件分成更小的部分,在第一个部分完成后请求下一个部分(或者甚至同时请求多个部分以提高性能)。如果有异常,那么您可以处理未来的请求,因此它们永远不会从一开始就开始。

YouTube 和一些流媒体网站不久前就开始这样做了。过去,如果您开始播放视频,然后暂停,它最终会缓存整个视频。现在它只在当前位置之前缓存一点。由于视频的放弃率,这节省了大量带宽。

您可以将部分文件写入磁盘或保存在内存中。