最近工作中需要用qftp循环去连接不同的ip,自动进行下载不同设备的文件,使用过程中踩了很多坑,现在记录一下:
1.qftp这个类是异步工作方式,简单来说它就是通过信号和槽的方式进行工作的。它自身带有
connect(m_ftp, &QFtp::commandStarted, this, &DownThread::ftpCommandStarted); connect(m_ftp, &QFtp::commandFinished, this, &DownThread::ftpCommandFinished); connect(m_ftp, &QFtp::listInfo, this, &DownThread::addToList);这三对信号和槽。
当使用 m_ftp->connectToHost(),发出commandStarted信号,设备连接成功后会发出commandFinished信号,我们可以在它对应的槽函数里进行一系列操作。
void DownThread::ftpCommandStarted(int)
{
int id = m_ftp->currentCommand();
switch (id)
{
case QFtp::ConnectToHost :
qDebug() <<"正在连接到服务器…";
break;
case QFtp::Login :
qDebug() <<"正在登录…";
break;
case QFtp::Get :
qDebug() <<"正在下载…";
break;
case QFtp::Close :
qDebug() <<"正在关闭连接…";
case QFtp::Cd :
qDebug() <<"正在进入目录…";
}
}
void DownThread::ftpCommandFinished(int, bool error)
{
if(m_ftp->currentCommand() == QFtp::ConnectToHost) {
if (error)
qDebug() <<tr("连接服务器出现错误");
else qDebug() <<tr("连接到服务器成功");
} else if (m_ftp->currentCommand() == QFtp::Login) {
if (error)
qDebug() <<tr("登录出现错误");
else {
qDebug() <<"登录成功";
}
} else if (m_ftp->currentCommand() == QFtp::Get) {
if(error)
qDebug() <<tr("下载出现错误:%1").arg(m_ftp->errorString());
else {
qDebug() <<"已经完成下载";
}
} else if (m_ftp->currentCommand() == QFtp::List) {
qDebug()<<"进入列表";
} else if (m_ftp->currentCommand() == QFtp::Close) {
}else if(m_ftp->currentCommand()==QFtp::Cd )
{
if(error)
qDebug() <<tr("进入目录出现错误:%1").arg(m_ftp->errorString());
else {
qDebug() <<"进入目录成功";
}
}
}
如果只是对一个设备进行连接,那一般不需要有特殊的地方,但如果你需要不断地去循环创建连接和下载,一定要缕清顺序,例如等连接成功再执行登录命令,等登录成功再进行进入目录等等。
2.关于编码不一致问题:
qftp类它有一个问题所在之处就是因为编码不一致会导致下载文件错误或者无法下载,下面写出如何避免因编码不一致导致下载出错的问题:
(1)进入目录时字符转换
QString name=QLatin1String(Infor::sg_workList.dequeue().toUtf8());
QString path="/";
path+=name;
m_ftp->cd(name);
(2)通过list()去获取文件目录时,获取回来的文件名称转换
void DownThread::addToList(const QUrlInfo &urlInfo)
{
QString name= QString::fromLocal8Bit(urlInfo.name().toLatin1());
m_fileNameList.append(name);
}
(3)开始要下载时,文件名字转成ftp的编码
for (int i = 0; i < m_fileNameList.length(); i++) {
QString fileName= nameList[0];
QString name = fileName.toLocal8Bit();
QString remoteName =QString("E:/FileServer")+ "/" + name;
m_file =new QFile(remoteName);
if(m_file->exists())
{
int nId = QMessageBox::question(nullptr, "提示信息", "文件已存在,是否替换", "是", "否");
if(nId != 0) {
delete m_file;
return;
}
}
if (!m_file->open(QIODevice::Truncate | QIODevice::WriteOnly)) {
delete m_file;
return;
}
m_ftp->get(QString::fromLatin1(fileName.toLocal8Bit()), m_file);
}
2.文件下载后空白的原因:
ftp在get()成功后,一定要在ftpCommandFinished()这个槽函数中将文件关闭,否则下载后一定是空文件。