您的位置:首页 > 编程语言 > Qt开发

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

2017-06-25 14:51 2441 查看
最近在做一个小项目,需要向一个服务器批量上传本地文件,通过表单数据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、需要定义postData和onPostDataFinish两个函数,分别执行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;  //这一句是关键,用来释放上传结束后文件的内存
}


4、post流程说明

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

 

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

只要对上述定义的Uploader类进行合理的线性控制,就可以利用这个类完成批量上传工作。由于QNetworkAccessManager本身是异步的,因此上传过程中即使该类运行在Qt的主线程下,也并不会造成交互的卡顿。当然如果想要多线程操作,可以让Uploader继承QTread类,并在上一级多开几个Uploader实例,对任务进行分发。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: