对Qt的QFtp类太失望了, O_O...所以...
libcurl-7.19.3-win32-ssl-msvc.zip
选择windows系统的, 下载MSVC 带ssl的
在虚拟机上用FileZilla搭建一个FTP服务器并创建可匿名空密码登录; 在Qt工程中包含必须的头文件, 引用必须的lib文件; 测试可以正常下载到文件
支持ftp文件上传下载, 断点续传, 文件传输进度; 有待测试验证
听说很强大而且性能不错, 真喜欢
要实现的功能:
1.断点续传
2.进度回馈 (下载百分比, 文件大小, 已下载大小, 下载速度...)
3.暂停(断开数据传输连接, 不删除本地缓存数据)
4.取消(断开数据传输连接, 并删除本地缓存数据)
5.超时(连接超时-重连; 超时未收到数据流-重连; 整个下载任务过程超时-记录并取消下载)
6.重连(断开实连接或虚连接)
7.实连接(连接时通的, 可以正常收发数据包)
8.虚连接(连接已经断开但程序没检测到, 以为链路是通的)
9.限速(防止cup爆满; 防止网络流量大量占用 -服务端ftp工具可配置最大传输速度, 客户端程序也可提供相应配置接口)
10.要可以浏览远程ftp服务器上的目录文件
遇到的问题:
1.路径的编码和文件名的编码不一样?
现象: A情况 ftp路径若包含中文字符, 文件名是英文字符 Qt代码: curl_easy_setopt(this->curl, CURLOPT_URL, url.toLocal8Bit().data()); 可行 B情况 ftp路径若包含中文字符, 文件名也包含中文字符 同样的代码执行会失败 FileZilla服务端的监控工具看到文件名变成乱码 但Qt代码为: curl_easy_setopt(this->curl, CURLOPT_URL, url.toStdString().c_str()); 是可行的, 但这样对于A情况就不行 解决思路1:(验证过了, 行不通) 把路径和文件名分开, 路径用toLocal8Bit转换编码, 文件名用toStdString转换
解决思路2:(已验证, ok)
百度一下, 听说FileZilla编码用的是utf8, 所以只要把url路径转成utf8格式就ok了
curl_easy_setopt(this->curl,CURLOPT_URL,url.toUtf8().data()); //A B情况都行
缺陷, 下载其他ftp服务器(非FileZilla)的文件又有编码问题
据说可以给FileZilla服务端打编码问题的补
解决思路3:(发神经了, 这样就行了嘛...)
curl_easy_setopt(this->curl,CURLOPT_URL,url.toLocal8Bit().data());
2.不知道怎么实现浏览远程ftp服务器目录文件
经过困难的百度, 了解到可以直接发送FTP命令LIST(或NLST)来实现 一开始不知道发送命令后, 如何获取结果; 后来猜测是跟文件下载的回调函数是同一个回调, 结果我猜对了.. 测试: curl_easy_setopt(easy_handle, CURLOPT_CUSTOMREQUEST, "NLST"); 可以返回文件名列表 --可以很简单的处理 curl_easy_setopt(easy_handle, CURLOPT_CUSTOMREQUEST, "LIST"); 可以返回目录文件信息列表 --返回的格式稍微复杂一些....懒得去研究, 所以直接看Qt源码, 看它怎么处理LIST命令返回的结果, 然后直接考出它里面的代码来用, 直接ok了
3.发布的时候提示没找到libsasl.dll动态库?
下载的libcurl库压缩包里面根本没提供libsasl.dll这个动态库
我奇怪为啥在我的机器上能跑; 到其他机器上就提示未找到这个文件
后来全盘扫描本地文件, 发现svn安装目录下有这个动态库文件, 而svn目录已添加到环境变量里面; 所以本机可以运行
解决方案: 把这个dll拷过去
4.线程发射信号问题
主线程创建一个从QThread类继承下来的工作线程, 有一个QObject继承下来的类对象成员, 该成员可以发出一个信号, 信号的参数是一个普通的类对象
这样没错, 可以关联成员发出信号后, 被主线程接收
class Param { .... }; class Obj : QObject { .... signals: void sXXX(Param); }; class Thread : public QThread { public: .... private: Obj obj; }; //主线程可以间接关联到Obj对象发出的信号
如果是这样的话就不行了:
class Param { .... }; class Obj : QObject { .... signals: void sXXX(Param); }; class ThreadA : public QThread { public: ... private: Obj obj; }; class ThreadB : public QThread { public: .... private: ThreadA* threadA; };
//主线程创建ThreadA线程, ThreadA线程创建ThreadB线程, ThreadB线程类对象的obj成员发出的信号, 不能间接的关联到主线程中去
好像关联上去; 该如何如何...
解决方案:
把线程对象由局部对象提升到成员变量