使用Qt开发FTPClient的问题

Posted

技术标签:

【中文标题】使用Qt开发FTPClient的问题【英文标题】:Problem in developing FTPClient using Qt 【发布时间】:2010-12-01 12:07:57 【问题描述】:

我正在尝试使用 QT Network 实现 FTPClient。

我该如何处理下载过程中的特殊情况,例如网线被拔掉,没有互联网连接等等......?

我的 FTPClient 怎样才能知道此类事件,是否有此类通知可用?

我尝试使用 done(bool) 、 ommandFinished (int id, bool error) 等信号,但我没有收到任何类型的信号。

【问题讨论】:

【参考方案1】:

您似乎使用过时的 QFtp。你应该使用 QNetworkReply(和 QNetworkAccessManager),它已经完成()和错误()信号: QNetworkReply documentation。

【讨论】:

我正在使用 Qt 4.7 库。它会下载文件,但我没有收到此类事件。 不过,QFtp 已经过时并且可能有问题。你试过 QNetworkReply 吗? 我认为说服 Ashish 将 QNAM 用于 FTP 客户端是不对的。 QNAM 充当需要处理不同协议的应用程序的抽象层。相反,FTP 客户端在设计上只能使用 FTP 协议,它可能需要比通用 QNAM 接口中公开的功能更复杂的功能。 来自 QFtp apidocs:“这个类提供了一个到 FTP 的直接接口,允许你对请求有更多的控制。但是,对于新的应用程序,建议使用 QNetworkAccessManager 和 QNetworkReply,因为那些类拥有更简单但更强大的 API。”它没有明确标记为过时,但 QHttp 也是如此(我认为 QFtp 也是如此),只要你是对的。不过,我希望这些天来更好地支持 QNAM。不过,我自己并没有大量使用它来进行 FTP。【参考方案2】:

您是否尝试过创建自定义 SLOT 并将其连接到 QNetworkReply 错误 SIGNAL?

然后您可以检查参数以确定错误并决定如何处理它。

QNetworkReply::NoError  0   no error condition. Note: When the HTTP protocol returns a redirect no error will be reported. You can check if there is a redirect with the QNetworkRequest::RedirectionTargetAttribute attribute.
QNetworkReply::ConnectionRefusedError   1   the remote server refused the connection (the server is not accepting requests)
QNetworkReply::RemoteHostClosedError    2   the remote server closed the connection prematurely, before the entire reply was received and processed
QNetworkReply::HostNotFoundError    3   the remote host name was not found (invalid hostname)
QNetworkReply::TimeoutError 4   the connection to the remote server timed out
QNetworkReply::OperationCanceledError   5   the operation was canceled via calls to abort() or close() before it was finished.
QNetworkReply::SslHandshakeFailedError  6   the SSL/TLS handshake failed and the encrypted channel could not be established. The sslErrors() signal should have been emitted.
QNetworkReply::TemporaryNetworkFailureError 7   the connection was broken due to disconnection from the network, however the system has initiated roaming to another access point. The request should be resubmitted and will be processed as soon as the connection is re-established.
QNetworkReply::ProxyConnectionRefusedError  101 the connection to the proxy server was refused (the proxy server is not accepting requests)
QNetworkReply::ProxyConnectionClosedError   102 the proxy server closed the connection prematurely, before the entire reply was received and processed
QNetworkReply::ProxyNotFoundError   103 the proxy host name was not found (invalid proxy hostname)
QNetworkReply::ProxyTimeoutError    104 the connection to the proxy timed out or the proxy did not reply in time to the request sent
QNetworkReply::ProxyAuthenticationRequiredError 105 the proxy requires authentication in order to honour the request but did not accept any credentials offered (if any)
QNetworkReply::ContentAccessDenied  201 the access to the remote content was denied (similar to HTTP error 401)
QNetworkReply::ContentOperationNotPermittedError    202 the operation requested on the remote content is not permitted
QNetworkReply::ContentNotFoundError 203 the remote content was not found at the server (similar to HTTP error 404)
QNetworkReply::AuthenticationRequiredError  204 the remote server requires authentication to serve the content but the credentials provided were not accepted (if any)
QNetworkReply::ContentReSendError   205 the request needed to be sent again, but this failed for example because the upload data could not be read a second time.
QNetworkReply::ProtocolUnknownError 301 the Network Access API cannot honor the request because the protocol is not known
QNetworkReply::ProtocolInvalidOperationError    302 the requested operation is invalid for this protocol
QNetworkReply::UnknownNetworkError  99  an unknown network-related error was detected
QNetworkReply::UnknownProxyError    199 an unknown proxy-related error was detected
QNetworkReply::UnknownContentError  299 an unknown error related to the remote content was detected
QNetworkReply::ProtocolFailure  399 a breakdown in protocol was detected (parsing error, invalid or unexpected responses, etc.)

其中一些错误代码特定于 HTTP,但其他错误代码更通用。

【讨论】:

【参考方案3】:

要在使用 QFtp 时处理网络异常,您可以监听 stateChanged() 信号。如果状态变为 Closing 或 Unconnected,您可以检查 error() 是什么。

关于 QNAM 与 QFtp:QNAM 是更干净和更新的 api,但两者都非常适合工作并得到官方支持。在 API 方面,QFtp 使用旧的命令 ID 模式(每个命令返回一个命令 ID),这要求我们跟踪命令(例如:找出发出信号的命令)。我发现 QNAM 的 api 模式要好得多,因为它的命令返回一个 QNetworkReply 对象,该对象反过来发出信号。但是,QNAM 的 api 似乎并没有针对 ftp 进行调整,也无法处理 http/s(如 no deletion of files over ftp),所以也许你现在最好坚持使用 QFtp。

【讨论】:

【参考方案4】:

这是complete example of an QT FTP client,以及文档。我建议在 QFTP class 周围使用他们的包装器。

下载时处理错误的摘录:

 if (ftp->currentCommand() == QFtp::Get) 
     if (error) 
         statusLabel->setText(tr("Canceled download of %1.")
                              .arg(file->fileName()));
         file->close();
         file->remove();
      else 
         statusLabel->setText(tr("Downloaded %1 to current directory.")
                              .arg(file->fileName()));
         file->close();
     
     delete file;
     enableDownloadButton();
     progressDialog->hide();

这也是一个完整的演示。截图如下:

【讨论】:

是的,我知道这是有效的,但是当网络被禁用时它不会给出任何事件。 当网络断开时,客户端应该认为下载已经“完成”,然后这段代码就会触发。这不是正在发生的事情吗?【参考方案5】:

QNetworkAccessManager,正如我无法回答的 cmets 中所述,是满足常见需求的基本网络实用程序,不适用于低级别访问。

您可以做的选择很少:

1) 自己实现 FTP 协议以及使用 QTcpSocket 和服务器所需的所有功能。

2) 使用 QNetworkAccessManager 并希望您可以解决所有问题。

每种方法的好处应该很清楚,但请记住,Qt 不仅仅是用于创建 FTP 客户端的工具包。

【讨论】:

以上是关于使用Qt开发FTPClient的问题的主要内容,如果未能解决你的问题,请参考以下文章

FTPClient listFiles 阻塞问题

FtpClient上传文件速度非常慢,而且大小为0,上传失败

记录 FTPClient 超时处理的相关问题

记录 FTPClient 超时处理的相关问题

使用 org.apache.commons.net.ftp.FTPClient 保护 FTP

apache的ftpClient使用记录