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实例:
3、需要定义postData和onPostDataFinish两个函数,分别执行post动作、处理post结果,前者是普通调用函数,后者是槽函数。
(a)、其中postData函数定义:
(b)、onPostDataFinish槽函数的定义:
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实例,对任务进行分发。
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实例,对任务进行分发。
相关文章推荐
- HttpClient PostMethod模拟带文件上传+普通字段的http请求(可解决文件为网络文件的问题)
- httpClient4.3 模拟Post提交,模拟Post上传文件并解决服务端使用spingMVC时upload.parseRequest(request)解析不到File,Pos简单抓取页面数据
- HttpClient4.5.2模拟表单post提交上传文件
- Python模拟HTTP Post上传文件
- 基于libcap的网络包分析问题集锦续(http post方式上传文件)
- java、 http模拟post上传文件到服务端 模拟form上传文件
- HTTP POST的文件上传问题
- HTTPCLIENT POST 模拟有上传文件和文本字段的动态表单
- asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端
- 【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端
- Qt通过HTTP POST上传文件
- 关于通过http post进行文件上传的问题
- httpurlconnection模拟post提交form表单(普通文本和上传文件) (
- 基于libcap的网络包分析问题集锦(http post方式上传文件)
- httpclient post 上传文件及参数包括中文乱码问题方案
- 利用HttpURLConnection发送post请求上传多个文件
- 模拟提交有文件上传的表单(通过http模拟上传文件)
- java中使用scoket模拟http post请求发送图片或文件
- VBS模拟POST上传文件的代码
- android模拟post请求上传文件