java ajax 断点续传_文件批量上传的工具,要实现暂停继续、断点续传等功能(使用QtNetwork和QHttpMultiPart,和定时器检查超时)...

博主分享了在使用Qt的QtNetwork模块开发文件批量上传工具时遇到的问题,即内存占用随上传进度增加而上升,导致程序崩溃。通过深入分析发现,`QObject::deleteLater`的使用不当造成了内存释放延迟。最终通过调整代码,使用`QScopedPointer`确保对象销毁时机正确,解决了内存泄漏问题。
摘要由CSDN通过智能技术生成

最近在做一个文件批量上传的工具,要实现暂停继续、断点续传等功能。利用Qt自带的QtNetwork模块,完成这些需求并没有费多少周章,主要思路就是将文件分块,然后用while循环依次传输。具体实现代码比较复杂,简化了一下大致是这样子的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

int chunkUpload(UploadItem *item, const qint64 &chunkSize)

{

Q_ASSERT(item != 0);

// ...

QNetworkRequest request;

QNetworkReply* reply;

QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

QBuffer* buffer = new QBuffer(multiPart);

QEventLoop loop;

QTimer timer;

// ... append fields to multiPart ...

request.setUrl(UPLOAD_URL);

reply = networkManager->post(request, multiPart);

// 保证reply销毁的时候multiPart和buffer也会随之销毁。

multiPart->setParent(reply);

// 加入一个消息循环,reply传输完成前进程会一直阻塞在这里;并设置一个定时器,如果传输超时则强制跳出消息循环

timer.setSingleShot(true);

timer.setInterval(NetworkTimeout);

connect(reply, SIGNAL(uploadProgress(qint64,qint64)), &timer, SLOT(start()));

connect(reply, SIGNAL(downloadProgress(qint64,qint64)), &timer, SLOT(start()));

connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);

connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);

timer.start();

loop.exec();

reply->deleteLater();

if (reply->isRunning())

reply->abort();

if (reply->error() != QNetworkReply::NoError)

return -1;

// ... deal with the reply ...

return 0;

}

void upload()

{

while (NOT_FINISHED) {

chunkUpload(item, CHUNK_SIZE);

}

}

程序编译运行过程很顺利,测试的时候也没发现什么问题。但后来我随手上传了一个1G大小的文件,发现每次文件上传到70%左右的时候程序就崩溃了,小文件就没这个问题。急忙打开任务管理器,这才发现上传文件的时候,程序内存占用会随着上传进度的增加而增加,上传1G文件的时候内存最多会吃到1.5G,这时候程序申请不到更多内存了,我又没做检查,当然就会崩溃掉。

限制上传文件大小这种事我是不会做的,毕竟一个上传工具占用内存比PS都高实在不科学。注意到文件上传完成之后内存会立即回到正常值,显然原因并不是我忘记释放内存而是内存释放不及时,这样看来唯一可疑的地方就是上面chunkUpload函数里面的reply->deleteLater()那一句了吧。于是我写了个方法监听reply的销毁时机,果然每一块上传完成之后reply没有销毁,直到文件全部上传完毕之后才输出一大堆“I’m destroyed…”的信息。

根据Qt文档的说明,QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象。我在这里使用deleteLater只是因为Qt文档里推荐这么做而已,其他并没多想。是这样的话一切都说得通了,因为chunkUpload函数是在一个while循环里,程序还没来得及处理这个event就立即进行下一块传输了,传输过程中生成的QNetworkReply以及它关联的QBuffer、QHttpMultiPart当然也就来不及删除了。崩溃原因找到了。你不就是来不及处理销毁对象的event嘛,手动让你处理下不就行了?于是修改upload函数代码如下:

1

2

3

4

5

6

7

void upload()

{

while (NOT_FINISHED) {

chunkUpload(item, CHUNK_SIZE);

qApp->processEvents(); // 让主程序把消息队列中的QEvent处理完

}

}

编译、运行,内存占用依然没有改变,看样子加这一行用处不大。再次查询QObject::deleteLater()的文档,发现这样一句话:

…for the object to be deleted, the control must return to the event loop from which deleteLater() was called.

这么说来,deleteLater销毁QObject的唯一时机就是程序返回主消息循环以后了呢。无奈只能放弃deleteLater。考虑到每次return前都要手动delete亦或是使用goto语句实在都不够优雅,所以利用Qt自带的QScopedPointer,修改chunkUpload函数如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

int chunkUpload(UploadItem *item, const qint64 &chunkSize)

{

Q_ASSERT(item != 0);

// ...

QNetworkRequest request;

QScopedPointer<QNetworkReply> reply;

QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

QBuffer* buffer = new QBuffer(multiPart);

QEventLoop loop;

QTimer timer;

// ... append fields to multiPart ...

request.setUrl(UPLOAD_URL);

reply.reset(networkManager->post(request, multiPart));

multiPart->setParent(reply.data());

// ... event loop ...

if (reply->isRunning())

reply->abort();

if (reply->error() != QNetworkReply::NoError)

return -1;

// ... deal with the reply ...

return 0;

}

问题解决。

https://blog.yeatse.com/2015/03/18/qobject-deletelater-usage/

带进度条的文件批量上传插件uploadify

有时项目中需要一个文件批量上传功能时,个人认为uploadify是快速简便的解决方案. 先上效果图: 一. 下载uploadify 从官网下载uploadify的Flash版本(Flash版本免费,另 ...

文件批量上传-统一附件管理器-在线预览文件&lpar;有互联网和没有两种&rpar;--SNF快速开发平台3&period;0

实际上在SNF里使用附件管理是非常简单的事情,一句代码就可以搞定.但我也要在这里记录一下统一附件管理器能满足的需求. 通用的附件管理,不要重复开发,调用尽量简洁. 批量文件上传,并对每个文件大小限制, ...

使用WebUploader实现文件批量上传,进度条显示功能

知识点:利用WebUploader,实现文件批量上传,并且实时显示文件的上传进度 参考官方文档:http://fex.baidu.com/webuploader/ (1)引入三个资源 JS,CSS,S ...

jquery文件批量上传控件Uploadify3&period;2&lpar;java springMVC&rpar;

人比較懒  有用为主 不怎么排版了 先放上Uploadify的官网链接:http://www.uploadify.com/  -->里面能够看到PHP的演示样例,属性说明,以及控件下载地址.分f ...

SpringMVC&plus;Ajax实现文件批量上传和下载功能实例代码

需求: 文件批量上传,支持断点续传. 文件批量下载,支持断点续传. 使用JS能够实现批量下载,能够提供接口从指定url中下载文件并保存在本地指定路径中. 服务器不需要打包. 支持大文件断点下载.比如下 ...

利用uploadify&plus;asp&period;net 实现大文件批量上传。

前言 现在网上文件上传组件随便一搜都是一大堆,不过看大家一般都在用uploadify这个来上传文件.由于项目需要,我在来试了一下.因为第一次使用,也遇到了很多问题,特此记录! ------------ ...

uploadify文件批量上传

uploadify能够时间文件的批量上传,JS文件包下载地址,使用说明可以参考官网文档(http://www.uploadify.com/documentation/) 使用方法如下代码: $(&qu ...

stringMVC&lowbar;09文件批量上传

一.思路 在文件上传的基础上引入数组可以实现批量上传,只需要更改一下前段页面和controller类即可 文件上传: https://www.cnblogs.com/aihuadung/p/10167 ...

ASP&period;NET MVC WebAPI实现文件批量上传

工作中学习,学习中记录~~~~~~ 最下面附上demo 任务需求:需要做一个apI接口让C#的程序调用实现批量文件的上传. 难度: 没有做过通过API上传文件的...之前做过网站前后台上传. 首先当然 ...

随机推荐

c&num;链接数据库

using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; usin ...

HOJ 1640 Mobile Phone

题意:有一个n*n的矩阵,op==1时,在(x,y)增加值z,op==2时,求以(x1,y1)和(x2,y2)构成的矩阵的和. 思路:二维线段树. 代码: #include

WebService优点和缺点小结&lpar;转&rpar;

一.什么是WebService? 实际上,WebService的主要目标是跨平台的可互操作性.为了达到这一目标,WebService完全基于XML(可扩展标记语言).XSD (XMLSchema) ...

hdu4638 group 树状数组

连接:http://acm.hdu.edu.cn/showproblem.php?pid=4638 题意:就给给你n个数(大小在1-n里),然后给你连续的可以构成一个块,再给你N个询问,每个询问一个l ...

oracle行转列

wm_concat()函数 --创建表 create table test(id number,name varchar2(20)); --插入数据 insert into test values(1 ...

Ribbon Control

https://documentation.devexpress.com/#WindowsForms/CustomDocument2492 The Ribbon Control replaces tr ...

初时Python博大精深

Python是解释型语言 编译型vs解释型 编译型优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高.可以脱离语言环境独立运行.缺点:编 ...

天马行空-Ops平台建设概述

1           概述 什么是Ops平台,Ops平台的目标是什么,建设的考虑点有哪些?本章节以实际生活中医院的例子来进行各形象的阐述. 医院包含各种诊断治疗设备,病历库,医生.一个孕妇需要到医院 ...

JavaScript中对象属性的加入和删除

...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值