Delphi - 使用套接字从 Web 下载文件

Posted

技术标签:

【中文标题】Delphi - 使用套接字从 Web 下载文件【英文标题】:Delphi- downloading files from the web with sockets 【发布时间】:2013-02-08 22:58:32 【问题描述】:

我尝试过 Synapse、Indy 和 ICS,但我对它们不满意。我想同时下载多个部分的多个文件,支持恢复、gzip 编码的文件、cookie、使用 POST 登录网站等。所以我想我会用套接字写。 但我看到 Delphi 中有很多可用的套接字:TTcpClient、TRawSocket、TCGIRequest、TClientSocket 等等。它们都没有完整的文档记录——很难找到使用示例。我尝试使用 TTcpClient 但有时程序会冻结然后超时,我不知道为什么。等待回复时似乎有问题。这肯定不是服务器问题,因为我在 localhost 上进行了测试。 用于 HTTP 协议的最佳套接字是什么?好用吗?

我想在 Delphi 7 和 XE2 中都使用。我不想使用 WinAPI 之类的任何东西,所以我不必处理 PChars 和其他非 Delphi 的东西。

我正在考虑类似的东西:

1) 完全符合我的要求 - 在同一个文件中下载多个带有多个文件进度条的片段

2) 类似 telnet- 所以我只是将 HTTP 命令编写为字符串,然后我得到字节数组作为回报,我可以将其转换为字符串或保存到 tstreams 中。

【问题讨论】:

试试 WinInet。 Delphi 完全支持它;它不需要任何附加组件。它可能非常适合您的目的:cryer.co.uk/brian/delphi/wininet.htm 印地有什么问题?还是异步 ICS(可能更适合并行文件下载)? 更进一步,您使用的是什么版本的 Delphi? TClientSocket 现在已经过时了,即使在旧版本的 Delphi 中支持,仍然强烈建议不要考虑使用它们。 Delphi 版本对于这样的问题很重要。更不用说这首先对 *** 来说不是一个合适的问题。 “我应该使用什么”对于 S/O 来说是一个糟糕的问题,“易于使用的东西”更糟糕,它是主观的。两者结合在一起是一个可怕的问题。 @Tom:TIdHTTP 支持你所要求的一切,你只需要知道如何使用它。详情见我的回答。 【参考方案1】:

我无法评论其他库,但 Indy 支持您所要求的一切。

如果服务器支持,TIdHTTP 组件可以使用字节范围下载文件。您可以使用TIdHTTP.Head() 方法检查服务器是否返回给定URL 的Accept-Ranges: bytes 标头。如果是这样,那么您可以在从该 URL 下载数据时根据需要将 TIdHTTP.Request.ContentRangeStartTIdHTTP.Request.ContentRangeEnd 属性设置为所需的字节偏移量。要同时下载资源的多个部分,只需并行运行多个线程,每个线程都有自己的TIdHTTP 组件。然后,您必须下载多个片段以分隔临时文件,然后在完成后将它们合并到最终文件中,或者创建一个预先确定大小的文件,然后在所需的起始偏移量处打开多个 TFileStream 对象TIdHTTP 写信给。

TIdHTTP 支持 cookie。您可以将TIdCookieManager 组件分配给TIdHTTP.CookieManager 属性,或者您可以不分配它,TIdHTTP 将在内部创建一个TIdCookieManager 对象。无论哪种方式,还要将 TIdHTTP.AllowCookies 属性设置为 True。

根据服务器是使用基于 HTTP 的身份验证还是基于 WebForm 的身份验证,可以使用两种不同的方式之一来完成网站登录:

    1234563然后根据需要设置TIdHTTP.Request.UserNameTIdHTTP.Request.Password 属性。如果 WebServer 在请求期间要求进行身份验证,TIdHTTP 将选择适当的类并使用它使用指定的凭据登录。如果服务器拒绝凭据,TIdHTTP.OnAuthorization 事件将被触发,让您有机会更改凭据并重试。

    对于 WebForm 身份验证,有一个 TIdMultipartFormDataStream 类可以传递给 TIdHTTP.Post() 方法,用于发布 multipart/form-data 格式的 POST 请求。

Indy 10 中的TIdHTTP 支持 gzip 文件和 deflate 压缩文件(Iny 9 和更早版本中的TIdHTTP 不支持压缩)。您可以将TIdZLibCompressorBase 派生组件(例如TIdCompressorZLib)分配给TIdHTTP.Compressor 属性,TIdHTTP 将为您处理所有细节,包括发送适当的Accept-Encoding 请求标头,并检查服务器的Transfer-Encoding 响应头。

TIdHTTP 具有OnWorkBeginOnWorkOnWorkEnd 事件,可用于进度条等。 OnWorkBegin 事件有一个 AWorkCountMax 参数,它指定传输的字节总数(如果已知),否则将为 0(使用 Content-Length 标头的 HTTP 响应将相应地设置 AWorkCountMax,但 HTTP 响应不会使用 Transfer-Encoding: chunked 标头)。 OnWork 事件有一个 AWorkCount 参数,它指定到目前为止已经传输了多少字节,而不管 AWorkCounMax 的值是多少。

【讨论】:

感谢您的回答和您的组件。由于我没有其他回复并且他们关闭了我的问题,我将再试一次 Indy :)

以上是关于Delphi - 使用套接字从 Web 下载文件的主要内容,如果未能解决你的问题,请参考以下文章

从android下载文件时出现套接字异常

如何使用套接字下载图像[重复]

Delphi用WinInet用用户名和密码下载文件

delphi如何删除目录和目录下的所有文件

Delphi - 本地路径的创建清空本地指定文件夹下的文件

从阻塞套接字更改为非阻塞套接字有啥好处?