abcdef

libcrul库

对Qt的QFtp类太失望了, O_O...所以...

官网: http://curl.haxx.se/

libcurl-7.19.3-win32-ssl-msvc.zip

选择windows系统的, 下载MSVC 带ssl的

在虚拟机上用FileZilla搭建一个FTP服务器并创建可匿名空密码登录; 在Qt工程中包含必须的头文件, 引用必须的lib文件; 测试可以正常下载到文件

支持ftp文件上传下载, 断点续传, 文件传输进度; 有待测试验证

听说很强大而且性能不错, 真喜欢

CurlTestProject

 

 

要实现的功能:

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成员发出的信号, 不能间接的关联到主线程中去

好像关联上去; 该如何如何...

解决方案:

把线程对象由局部对象提升到成员变量

posted @ 2013-02-20 15:25  jianc  阅读(1566)  评论(4编辑  收藏  举报