使用qftp或者qhttp下载文件
http://hi.baidu.com/ys%5Fshuoshu
项目中需要批量下载文件,一开始做了ftp的,后来考虑到客户安装ftp服务器会比较麻烦,正好还有web服务必须搭建,改写了程序用http方式下载。正好没有总结ftp下载程序,这里一起补上。
qt中提供的qftp和qhttp,都继承于qnetworkprotocol,它们使用方法也比较相似,只在细节上略有不同。
基本的一些代码:
1.声明对象,没有什么特别的。
QHttp *m_http = new QHttp( this );
QFtp *m_ftp = new QFtp( this );
2.建立连接,完全不同的命名方法,让人糊涂。
m_http->setHost(host,port);
m_ftp->connectToHost(host,port);
3.开始下载文件,返回值是下载编号,其实这里不是同步的,只是说明一下那些文件要下载,基本上下载之前这部分就结束了。
int id = m_http->get(path_source);
int id = m_ftp->get(path_source);
4.关闭连接
m_http->closeConnection();
m_ftp->close();
实际上只是上面这样是不行的,还要处理qftp和qhttp发出的信号:
1.得到连接状态:
stateChanged(int state)
qftp和qhttp的状态不完全相同,可以参考一下api。
2.处理下载文件:
qftp是readyRead()
qhttp是readyRead(const QHttpResponseHeader & resp)
这个是重点,这里面要通过currentId()方法取得下载编号,并判断正在下载的那个文件,使用writeBlock( char*, ulong )方法取得文件内容。
3.下载结束的处理,这里返回true表示出错,返回false表示下载成功。
qftp是ftpDone(bool error)
qhttp是httpDone(bool error)
这里记得返回true的话,判断一下state()的返回值是否等于QFtp::Connected或者QHttp::Connected,是的话关闭一下连接。
4.其他一些信号
qhttp的dataSendProgress(int done, int total),发出信息时发出,参数为已发出信息的bytes量和总发出bytes量。
qhttp的dataReadProgress(int done, int total),接受信息时发出,参数为已接受信息的bytes量和总接受bytes量。
qhttp的requestStarted(int id),开始下载一个文件时发出,参数为下载文件的编号
qhttp的requestFinished(int id, bool error),下载一个文件结束时发出,参数为下载文件的编号,和成功标识(true表示出错,false表示成功)
补充:这里使用的qt版本为3.3.8,操作系统linux,内核2.6,gcc版本是4.3.2。
下面是两个封装的类,实现了批量下载和下载进度的提示。
================================cftpclient.h=====================================
#ifndef CFTPCLIENT_H
#define CFTPCLIENT_H
#include <qobject.h>
#include <qftp.h>
#include <qprogressdialog.h>
#include <qapplication.h>
#include <qfile.h>
class CFtpClient : public QWidget
{
Q_OBJECT
public:
CFtpClient();
~CFtpClient();
void download( QString host, Q_UINT16 port, QStringList path_source, QStringList path_target, QString user, QString password );
private slots:
void ftpDone(bool error);
void cancel();
void stateChanged(int state);
void readyRead();
private:
QFtp *m_ftp;
QProgressDialog *m_qpd;
int m_total;
int m_step;
QStringList* m_path_target;
QMap<int,int> m_qm;
signals:
void success();
void fail();
};
#endif
================================cftpclient.cpp=====================================
/************************************************************
**name:ftp客户端类
**note:
**create date:2010-01-25
**creater:yushuo
**edit date:2010-01-25
************************************************************/
#include "cftpclient.h"
CFtpClient::CFtpClient()
{
// create the socket and connect various of its signals
m_step = 0;
m_total = 0;
m_ftp = new QFtp( this );
m_qpd = new QProgressDialog( QObject::trUtf8("文件下载中,请稍后!..."), QObject::trUtf8("取消"), m_total,this,QObject::trUtf8("提示"),false,WStyle_Customize | WStyle_NoBorder );
m_qpd->setPaletteBackgroundColor(QColor(222,199,241));
connect( m_ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)) );
connect( m_ftp, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)) );
connect( m_ftp, SIGNAL(readyRead()), this, SLOT(readyRead()) );
connect( m_qpd, SIGNAL(canceled()), this, SLOT(cancel()) );
}
CFtpClient::~CFtpClient()
{
delete m_ftp;
delete m_qpd;
}
void CFtpClient::download( QString host, Q_UINT16 port, QStringList path_source, QStringList path_target, QString user, QString password )
{
int id;
m_total = path_source.count();
if(m_total>0){
m_qpd->setTotalSteps(m_total);
m_path_target = &path_target;
if(m_ftp->connectToHost(host,port)){
if((user.isNull())||(user.isEmpty())||(password.isNull())||(password.isEmpty())){
if(m_ftp->login("tomcat", "tomcat")){
for(int i=0;i<m_total;i++){
id = m_ftp->get(*path_source.at(i));
m_qm.insert(id,i);
}
}
}else {
if(m_ftp->login(user,password)){
for(int i=0;i<m_total;i++){
id = m_ftp->get(*path_source.at(i));
m_qm.insert(id,i);
}
}
}
}
m_qpd->exec();
}
}
void CFtpClient::ftpDone(bool error)
{
if(error){
qDebug("CFtpClient::ftpDone===true");
m_step=m_total;
emit fail();
if ( m_ftp->state() == QFtp::Connected ){
m_ftp->close();
}
m_qpd->close();
}else {
qDebug("CFtpClient::ftpDone===false");
m_qpd->close();
emit success();
}
}
void CFtpClient::cancel()
{
m_ftp->abort();
m_step=m_total;
}
void CFtpClient::stateChanged(int state)
{
switch(state)
{
case QFtp::Unconnected:
qDebug("Ftp:Unconnected...");
break;
case QFtp::HostLookup:
qDebug("Ftp:HostLookup...");
break;
case QFtp::Connecting:
qDebug("Ftp:Connecting...");
break;
case QFtp::Connected:
qDebug("Ftp:Connected...");
break;
case QFtp::LoggedIn:
qDebug("Ftp:LoggedIn...");
break;
case QFtp::Closing:
qDebug("Ftp:Closing...");
break;
}
}
void CFtpClient:: readyRead()
{
int sort = 0;
int id = m_ftp->currentId();
QMap<int,int>::iterator qmIt;
if(m_qm.contains(id)){
qmIt = m_qm.find(id);
sort = qmIt.data();
}
qDebug("readyRead...%d..."+*m_path_target->at(sort),id);
ulong len = 0;
char data[1024];
QFile *file = new QFile(*m_path_target->at(sort));
m_step = sort;
m_qpd->setProgress(m_step);
if(!file->open(IO_WriteOnly | IO_Append)){
return;
}
while((len = m_ftp->readBlock( data, sizeof(data) ))>0){
file->writeBlock( data, len );
}
/*
QByteArray qba = m_ftp->readAll();
file->writeBlock(qba);
*/
file->close();
}
================================chttp.h=====================================
#ifndef CHTTP_H
#define CHTTP_H
#include <qobject.h>
#include <qhttp.h>
#include <qprogressdialog.h>
#include <qapplication.h>
#include <qfile.h>
class CHttp : public QWidget
{
Q_OBJECT
public:
CHttp();
~CHttp();
void download( QString host, Q_UINT16 port, QStringList path_source, QStringList path_target );
private slots:
void httpDone(bool error);
void cancel();
void stateChanged(int state);
void readyRead(const QHttpResponseHeader & resp);
void dataSendProgress(int done, int total);
void dataReadProgress(int done, int total);
void requestStarted(int id);
void requestFinished(int id, bool error);
void responseHeaderReceived(const QHttpResponseHeader & resp);
private:
QHttp *m_http;
QProgressDialog *m_qpd;
int m_total;
int m_step;
QStringList* m_path_target;
QMap<int,int> m_qm;
signals:
void success();
void fail();
};
#endif
================================chttp.cpp=====================================
/************************************************************
**name:http下载类
**note:
**create date:2010-03-17
**creater:yushuo
**edit date:2010-03-17
************************************************************/
#include "chttp.h"
CHttp::CHttp()
{
// create the socket and connect various of its signals
m_step = 0;
m_total = 0;
m_http = new QHttp( this );
m_qpd = new QProgressDialog( QObject::trUtf8("文件下载中,请稍后!..."), QObject::trUtf8("取消"), m_total,this,QObject::trUtf8("提示"),false,WStyle_Customize | WStyle_NoBorder );
m_qpd->setPaletteBackgroundColor(QColor(222,199,241));
connect( m_http, SIGNAL(done(bool)), this, SLOT(httpDone(bool)) );
connect( m_qpd, SIGNAL(canceled()), this, SLOT(cancel()) );
connect( m_http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)) );
connect( m_http, SIGNAL(readyRead(const QHttpResponseHeader&)), this, SLOT(readyRead(const QHttpResponseHeader&)) );
connect( m_http, SIGNAL(dataSendProgress(int, int)), this, SLOT(dataSendProgress(int, int)) );
connect( m_http, SIGNAL(dataReadProgress(int, int)), this, SLOT(dataReadProgress(int, int)) );
connect( m_http, SIGNAL(requestStarted(int)), this, SLOT(requestStarted(int)) );
connect( m_http, SIGNAL(requestFinished(int, bool)), this, SLOT(requestFinished(int, bool)) );
connect( m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), this, SLOT(responseHeaderReceived(const QHttpResponseHeader&)) );
}
CHttp::~CHttp()
{
delete m_http;
delete m_qpd;
}
void CHttp::download( QString host, Q_UINT16 port, QStringList path_source, QStringList path_target)
{
int id;
m_total = path_source.count();
if(m_total>0){
m_qpd->setTotalSteps(m_total);
m_path_target = &path_target;
m_http->setHost(host,port);
for(int i=0;i<m_total;i++){
id = m_http->get(*path_source.at(i));
m_qm.insert(id,i);
}
m_http->closeConnection();
m_qpd->exec();
}
}
void CHttp::httpDone(bool error)
{
if(error){
qDebug("CHttp::httpDone===true");
m_step=m_total;
emit fail();
if ( m_http->state() == QHttp::Connected ){
m_http->closeConnection();
}
m_qpd->close();
}else {
qDebug("CHttp::httpDone===false");
m_step=m_total;
m_qpd->close();
emit success();
}
}
void CHttp::cancel()
{
m_http->abort();
m_step=m_total;
}
void CHttp::stateChanged(int state)
{
switch(state)
{
case QHttp::Unconnected:
qDebug("QHttp:Unconnected...");
break;
case QHttp::HostLookup:
qDebug("QHttp:HostLookup...");
break;
case QHttp::Connecting:
qDebug("QHttp:Connecting...");
break;
case QHttp::Sending:
qDebug("QHttp:Sending...");
break;
case QHttp::Reading:
qDebug("QHttp:Reading...");
break;
case QHttp::Connected:
qDebug("QHttp:Connected...");
break;
case QHttp::Closing:
qDebug("QHttp:Closing...");
break;
}
}
void CHttp:: readyRead(const QHttpResponseHeader & resp)
{
int sort = 0;
int id = m_http->currentId();
QMap<int,int>::iterator qmIt;
if(m_qm.contains(id)){
qmIt = m_qm.find(id);
sort = qmIt.data();
}
qDebug("readyRead...%d..."+*m_path_target->at(sort),id);
ulong len = 0;
char data[1024];
QFile *file = new QFile(*m_path_target->at(sort));
m_step = sort;
m_qpd->setProgress(m_step);
if(!file->open(IO_WriteOnly | IO_Append)){
return;
}
while((len = m_http->readBlock( data, sizeof(data) ))>0){
file->writeBlock( data, len );
}
/*
QByteArray qba = m_ftp->readAll();
file->writeBlock(qba);
*/
file->close();
}
void CHttp::dataSendProgress(int done, int total)
{
qDebug("Sended %d bytes out of %d",done,total);
}
void CHttp::dataReadProgress(int done, int total)
{
qDebug("Downloaded %d bytes out of %d",done,total);
}
void CHttp::requestStarted(int id)
{
qDebug("CHttp::requestStarted==%d",id);
}
void CHttp::requestFinished(int id, bool error)
{
if(error){
qDebug("CHttp::requestFinished==%d==true",id);
qDebug(m_http->errorString());
}else {
qDebug("CHttp::requestFinished==%d==false",id);
}
}
void CHttp::responseHeaderReceived(const QHttpResponseHeader & resp)
{
qDebug("CHttp::responseHeaderReceived");
}