Qt模拟Http Post上传文件行为—内存释放问题

最近在做一个小项目,需要向一个服务器批量上传本地文件,通过表单数据formData格式提交给服务器,于是需要用Qt模拟这一行为。关于Qt模拟Http Post行为的博文很多,可以参考博文http://blog.sina.com.cn/s/blog_15d207b300102xvqz.html但是由于是批量上传文件,我发现按照博文中的内容进行操作,使用QNetworkAccessManager类会出现内存泄漏问题,即上传以后的文件数据不能得到有效的释放。于是查阅了一下Qt5.6的文档,下面给出正确的解决方案。


1假设用一个类Uploader来完成批量上传的工作,那么一个类只需要一个QNetworkAccessManager实例,可以声明类私有指针变量如下:

QNetworkAccessManager *networkManager;



2在类构造函数中new一个QNetworkAccessManager实例:

Uploader::Uploader(QObject *parent, QTextEdit *console) : QObject(parent)
{
    networkManager=new QNetworkAccessManager();
    connect(networkManager, &QNetworkAccessManager::finished, this, &Uploader::onPostDataFinish);

    .../*定义其它内容*/
}



3、需要定义postDataonPostDataFinish两个函数,分别执行post动作、处理post结果,前者是普通调用函数,后者是槽函数。


(a)其中postData函数定义:

void Uploader::postData()
{ 
    QString uuidboundry=QUuid::createUuid().toString();
    QByteArray formdata;

    .../*模拟生成合法的待发送的formdata数据,可参考其它博文*/

    QNetworkRequest request=QNetworkRequest(QUrl(uploadUrl));
    request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data;boundary="+uuidboundry).toLatin1());
    request.setRawHeader(QString("Content-Length").toLatin1(),QString::number(formdata.length()).toLatin1());
    networkManager->post(request,formdata);
}


(b)onPostDataFinish槽函数的定义:

void Uploader::onPostDataFinish(QNetworkReply *reply)
{
    QVariant statuscode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(statuscode==200&&reply->error() == QNetworkReply::NoError)
    {
        QByteArray bytes = reply->readAll();
        QString feedback(bytes);
        .../*上传成功,执行相应操作*/
    }
    else
    {
        .../*上传失败,执行相应操作*/
    }
    delete reply;  //这一句是关键,用来释放上传结束后文件的内存  
}



4post流程说明

注意onPostDataFinish槽函数在构造函数已经与QNetworkAccessManager::finished连接。当postData函数被调用,QNetworkAccessManager实例将执行post开始上传文件。完成上传工作以后,它会发射QNetworkAccessManager::finished(QNetworkReply *reply)信号,触发onPostDataFinish槽函数,开始处理post结果。此时,formdata的内存数据已经被移交relply因此,最后一句“delete reply”是关键,执行这一操作,就释放了已经上传成功的文件数据占用的内存,从而解决了前述的内存泄漏问题。

5、批量上传和多线程拓展

只要上述定义的Uploader类进行合理的线性控制,就可以利用这个类完成批量上传工作。由于QNetworkAccessManager本身是异步的,因此上传过程中即使该类运行在Qt主线程下,也并不会造成交互的卡顿。当然如果想要多线程操作,可以Uploader继承QTread类,并在上一级多开几个Uploader实例,对任务进行分发



猜你喜欢

转载自blog.csdn.net/sjy234sjy234/article/details/73716078