简述
Syncftp客户端基于Qt(Qt4或者Qt5都可以)的跨平台的FTP客户端,由于Qt4和Qt5对ftp支持有区别,为了代码统一,就选择了ftplib库作为ftp模块。
下载地址:https://download.csdn.net/download/no2101/12386832
设计
-
界面设计
界面分为菜单栏、工具栏、主界面和状态栏。
-
站点管理设计
- 新建站点
- 打开站点管理,即可看到新建的站点,双击即可登录。
FTP管理类设计
FTP管理类为:class FtpTransfer
- 具体代码:
//FtpTransfer.h代码
#ifndef FTPTRANSFER_H
#define FTPTRANSFER_H
#include <QObject>
#include <QFileInfoList>
#include <QDir>
#include <QTextCodec>
#include <QFileInfo>
#include "3rdparty/ftplib/ftplib.h"
struct REMFILE {
struct REMFILE *next;
fsz_t fsz;
char *fnm;
};
class FtpTransfer : public QObject
{
Q_OBJECT
public:
FtpTransfer(QObject *parent = 0);
void SetNetBuf(netbuf *conn)
{
pftp_conn = conn;
}
void SetTextCodec(QTextCodec *_codec)
{
codec=_codec;
}
void GetFtpDirFiles(const QString& path, const QString &dir,QStringList& total_list);
void Getfile2(const QString& remote_file , const QString &local_file);
void FindDirFiles(const QString& path, QFileInfoList& total_list);
void PutFile2(const QString &local_file , const QString& remote_file );
signals:
void Transferfinish(const QString &msg);
public slots:
void Getfile(const QString& remote_file , const QString &local_file);
void GetDir(const QString &ftp_path,const QString &ftp_dir,const QString &local_dir);
void PutFile(const QString &local_file , const QString& remote_file );
void PutDir(const QString &ftp_dir,const QString &local_dir);
private:
netbuf *pftp_conn;
QTextCodec *codec;
};
#endif // FTPTRANSFER_H
//FtpTransfer.cpp代码
#include "FtpTransfer.h"
#include <QThread>
#include <QDebug>
#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/stat.h>
#include <unistd.h>
#endif
static int log_progress(netbuf *ctl, fsz_t xfered, void *arg)
{
struct REMFILE *f = (struct REMFILE *) arg;
if (f->fsz){
double pct = (xfered * 100.0) / f->fsz;
printf("%s %5.2f%% %d \n", f->fnm, pct,xfered);
}else{
printf("%s %d \n", f->fnm, xfered);
}
fflush(stdout);
return 1;
}
FtpTransfer::FtpTransfer(QObject *parent) : QObject(parent)
{
pftp_conn = NULL;
}
void FtpTransfer::Getfile2(const QString &remote_file_str , const QString &local_file_str)
{
QByteArray Ba = codec->fromUnicode(remote_file_str);
char *remote_file = Ba.data();
QByteArray Ba2 = local_file_str.toLocal8Bit();
char *local_file = Ba2.data();
unsigned int fsz = 0;
struct REMFILE f;
f.next = NULL;
f.fnm = remote_file;
if (FtpSize(remote_file, &fsz, 'I', pftp_conn) == 0)
fsz = 0;
f.fsz = fsz;
fsz /= 100;
if (fsz > 100000)
fsz = 100000;
if (fsz == 0)
fsz = 32768;
FtpCallbackOptions opt;
opt.cbFunc = log_progress;
opt.cbArg = &f;
opt.idleTime = 1000;
opt.bytesXferred = fsz;
FtpSetCallback(&opt, pftp_conn);
int sts = FtpGet(local_file, remote_file, 'I', pftp_conn);
qDebug()<<"Getfile2"<<sts;
if (sts)
printf("%s retrieved\n", local_file);
}
void FtpTransfer::PutFile2(const QString &local_file_str , const QString& remote_file_str )
{
QByteArray Ba = codec->fromUnicode(remote_file_str);
char *remote_file = Ba.data();
QByteArray Ba2 = local_file_str.toLocal8Bit();
char *local_file = Ba2.data();
int sts = FtpPut(local_file, remote_file, 'I', pftp_conn);
if (sts)
printf("%s sent\n", local_file);
}
void FtpTransfer::Getfile(const QString &remote_file_str , const QString &local_file_str)
{
Getfile2(remote_file_str ,local_file_str);
emit Transferfinish(QString::fromLocal8Bit("下载文件%1完成").arg(remote_file_str));
}
/**
* 得到ftp服务器文件夹下的目录
*/
void FtpTransfer::GetFtpDirFiles(const QString& path,const QString &dir, QStringList& total_list)
{
QByteArray ba1 = codec->fromUnicode(path);
const char *ftp_path = ba1.constData();
QString total_dir = path;
if(path.compare("/")==0)
total_dir = total_dir + dir;
else
total_dir = total_dir + "/" + dir;
QByteArray Ba2 = codec->fromUnicode(total_dir);
FtpChdir(Ba2.constData(),pftp_conn);
netbuf *tempdir = NULL;
char buf[1024];
if (!FtpAccess(Ba2.constData(), FTPLIB_DIR_VERBOSE, FTPLIB_ASCII, pftp_conn, &tempdir)) {
printf("error requesting directory of %s-->%s\n", Ba2.constData(), FtpLastResponse(pftp_conn));
return;
}
QStringList dir_dir;
while (FtpRead(buf, 1024, tempdir) > 0){
char *p = strchr(buf, '\n');
if (p)*p = '\0';
QString Dir_verbose = codec->toUnicode(buf);
QStringList list1 = Dir_verbose.split(' ',QString::SkipEmptyParts);
QString _name;
for(int i=8;i<list1.size();i++){
_name.append(list1.at(i));
if(i+1<list1.size())
_name.append(" ");
}
QString _attribute = list1.at(0);
if(!_attribute.left(1).compare("d")){
dir_dir<<_name;
}else{
total_list<<total_dir+"/"+_name;
}
}
FtpClose(tempdir);
FtpChdir(ftp_path,pftp_conn);
for(int i=0;i<dir_dir.size();i++){
GetFtpDirFiles(total_dir,dir_dir.at(i),total_list);
}
}
void FtpTransfer::GetDir(const QString &ftp_path,const QString &ftp_dir,const QString &local_dir)
{
QStringList slist;
GetFtpDirFiles(ftp_path,ftp_dir,slist);
for(int i=0;i<slist.size();i++)
{
//qDebug()<<i<<ftp_path<<ftp_dir<<slist.at(i);
QString info = slist.at(i);
int lbak=0;
if(ftp_path.compare("/")!=0)
lbak=1;
QString temp = info.right(info.length()-ftp_path.length()-lbak);
QStringList dirlist1 = temp.split('/');
QDir ldir(local_dir);
for(int j=0;j<dirlist1.size()-1;j++)
{
if(!ldir.cd(dirlist1.at(j))){
ldir.mkdir(dirlist1.at(j));
ldir.cd(dirlist1.at(j));
}
}
ldir.cd(local_dir);
Getfile2(info,local_dir+"/"+temp);
}
emit Transferfinish(QString::fromLocal8Bit("下载文件夹%1完成").arg(ftp_dir));
}
void FtpTransfer::PutFile(const QString &local_file_str , const QString& remote_file_str )
{
PutFile2(local_file_str , remote_file_str );
emit Transferfinish(QString::fromLocal8Bit("上传文件%1完成").arg(local_file_str));
}
void FtpTransfer::FindDirFiles(const QString& path, QFileInfoList& total_list)
{
QDir dir(path);
dir.setFilter(QDir::Dirs|QDir::NoDotAndDotDot|QDir::Files|QDir::Hidden|QDir::NoSymLinks);
dir.setSorting(QDir::Name|QDir::DirsFirst);
QFileInfoList infolist = dir.entryInfoList();
foreach(QFileInfo info,infolist){
if(info.isDir()){
FindDirFiles(info.filePath(),total_list);
}else{
total_list.append(info);
}
}
}
void FtpTransfer::PutDir(const QString &ftp_dir,const QString &dir)
{
QByteArray ba = codec->fromUnicode(ftp_dir);
const char *path = ba.constData();
QFileInfoList dir_files_list;
FindDirFiles(dir,dir_files_list);
for(int i=0;i<dir_files_list.size();i++)
{
QFileInfo info = dir_files_list.at(i);
QString fullpath = info.path();
QString temp = fullpath.right(fullpath.length()-dir.lastIndexOf("/")-1);
QStringList dirlist1 = temp.split('/');
for(int j=0;j<dirlist1.size();j++){
QByteArray Ba = codec->fromUnicode(dirlist1.at(j));
const char *dir_path = Ba.constData();
int sts = FtpChdir(dir_path, pftp_conn);
// qDebug()<<dirlist1.at(j)<<sts<<ftp_dir;
if(sts != 1){
FtpMkdir(dir_path, pftp_conn);
FtpChdir(dir_path, pftp_conn);
}
}
PutFile2(info.filePath(),info.fileName());
FtpChdir(path,pftp_conn);
}
emit Transferfinish(QString::fromLocal8Bit("上传文件夹%1完成").arg(dir));
}
FtpTransfer使用
QThread* ftpThread = new QThread(this);
ftptransfer = new FtpTransfer();
ftptransfer->moveToThread(ftpThread);
ftptransfer->thread()->start();
connect(this,SIGNAL(signal_Connect()),this,SLOT(RootFTP()));
connect(this,SIGNAL(signal_connecterror(int)),this,SLOT(ConnectError(int)));
connect(this,SIGNAL(signal_GetFile(QString,QString)),ftptransfer,SLOT(Getfile(QString,QString)),Qt::QueuedConnection);
connect(this,SIGNAL(signal_GetDir(QString,QString,QString)),ftptransfer,SLOT(GetDir(QString,QString,QString)),Qt::QueuedConnection);
connect(this,SIGNAL(signal_PutFile(QString,QString)),ftptransfer,SLOT(PutFile(QString,QString)),Qt::QueuedConnection);
connect(this,SIGNAL(signal_PutDir(QString,QString)),ftptransfer,SLOT(PutDir(QString,QString)),Qt::QueuedConnection);
connect(ftptransfer,SIGNAL(Transferfinish(QString)),this,SLOT(UpdateFtpDir(QString)),Qt::QueuedConnection);
服务器字符编码
服务器的字符编码是由服务器决定的,一般的中文windows平台字符编码是GBK,而Linux平台为UTF8
如果没有设置正确字符,则有乱码。
-
测试
-
搭建ftp服务器
Linux下可以安装vsftpd,Windows下可以使用FileZilla_Server等。具体搭建方法可以到网上查一下。
-
新建站点
- 链接站点
双击即可登录
-
上传下载,鼠标右键