QNetworkAccessManager实现ftp功能总结

因为项目需要,第一次接触到FTP的上传问题,经过查阅后摈弃了旧的QFtp,采用新的QNetworkAccessManager。有关它的使用其实也很方便,已经提供了比较成熟的接口和信号,下面总结一下。

首先,在头文件创建一些变量和指针

	QUrl url;
    QNetworkAccessManager *accessManager; //初始化为nullptr
    QNetworkReply *reply;                 //初始化为nullptr
    QFile *ftp_file;                          //初始化为nullptr
    bool ftp_upload = false;  //上传文件标识
    bool ftp_download = false;  //上传文件标识

url是之后需要上传的FTP服务器文件路径;QNetworkAccessManager 就是所谓的网络访问管理器,主要靠它来进行文件上传;QNetworkReply 是QNetworkAccessManager 上传时的一个回复对象,可以通过它来得到一些返回的信息

然后,是cpp文件中正式代码部分

	//url
    QUrl url(uploadUrl);//设置一个ftp路径,例如ftp://xxx/xx/x
    url.setPort(ftp_upload_path_info.ftpport);//端口号
    url.setUserName(ftp_upload_path_info.ftpaccount);//用户名
    url.setPassword(ftp_upload_path_info.ftppws);//密码
	
	//给指针添加实例
    accessManager = new QNetworkAccessManager();
    accessManager->setNetworkAccessible(QNetworkAccessManager::Accessible);//设置可网络访问
    QNetworkRequest request(url);//将QUrl设置进网络请求类QNetworkRequest 中
	
	//该读取文件的方法,在1G以上的文件时会导致直接上传失败
	//ftp_file = new QFile(filenamepath);
    //ftp_file->open(QIODevice::ReadOnly);
    //QByteArray byte_file = ftp_file->readAll();
 
    //解决大文件的上传
    QFile *data = new QFile(filenamepath,this);
    if(data->open(QIODevice::ReadOnly))
    {

    }

    reply = accessManager->put(request, data/*byte_file*/);  //发送上传请求
    
    connect(accessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError)));
    connect(reply, SIGNAL(uploadProgress(qint64 ,qint64)), this, SLOT(loadProgress(qint64 ,qint64)));

代码不是很多,一步步来看。首先QUrl你要设置路径、端口号、用户名和密码,这是与FTP服务器相关的;然后就是正式的QNetworkAccessManager上传,你需要先把url设置进QNetworkRequest 对象中,再通过参数的形式传入QNetworkAccessManager的put方法中。put其实就是上传的意思,除了QNetworkRequest 参数外,你还需要一个文件指针。

这里有两种方法,网上主流的是先用QFile的readAll()来读取,但对于大文件是没办法readAll()的,所以会直接失败。这里将传入QByteArray 数据,改为直接传入QIODevice类型指针(QFile继承),从而解决大文件上传问题。亲测2G以上没问题,只是说文件越大上传速度肯定越慢嘛。
参考:解决QNetworkAccessManager实现ftp功能后,不能上传大于1G文件的问题

另外一个就是信号槽相关,这里我绑定了三条。第一条是QNetworkAccessManager本身的finished信号,这个不管是上传成功,还是上传失败,网络中断超时什么的都会返回,反正是一个结果,你需要通过QNetworkReply参数的错误参数来区分返回结果。

void xxx::replyFinished(QNetworkReply *)
{
    qDebug()<<"reply->error()"<<reply->error();
    if (reply->error() == QNetworkReply::NoError)  //每个文件上传完成都执行
    {
        qDebug()<<"上传成功";
        ftp_file->close();//文件操作要记得关闭

        QMessageBox::about(NULL, "提示", "上传成功!");

    }else if((reply->error() == QNetworkReply::OperationCanceledError))
    {
        //手动取消导致的错误
    }
    else
    {
//        QMessageBox::about(NULL, "提示", "上传失败!");
    }
}

第二条信号槽也是报错信息,跟第一条类似,但报错时机可能会有区别

void xxx::loadError(QNetworkReply::NetworkError error)
{
    qDebug()<<"Transmitted error!!!";
    //QMessageBox::about(NULL, "提示", "上传失败!");
}

第三条信号槽就有点意思了,它是上传进度的一个反馈信号,uploadProgress(qint64 ,qint64)的参数分别是当前已上传大小和总大小,例如250,1000这样。
这个信号的触发频率适中,可以用它来做一个进度条的显示。例如用QProgressBar的void setRange(int minimum, int maximum);和void setValue(int value);来设置范围和当前值。

值得一提的是,这里的参数都是int型,而大文件上传的情况下,往往uploadProgress(qint64 ,qint64)的qint64 (long long)是大于int的,如果不自行判断换算一下的话,进度条会没有任何效果和百分比数值哦。

while(bytesTotal > 0x7fffffff)//int的最大值
{
    bytesTotal /= 10;
    bytesSent /= 10;

}

你可能感兴趣的:(服务器,网络,linux,qt,c++)