[速度 VS 准确] 下载时保存下载进度 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
814084764
V2EX    程序员

[速度 VS 准确] 下载时保存下载进度

  •  
  •   814084764 2016-10-13 10:09:05 +08:00 3376 次点击
    这是一个创建于 3286 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在写下载模块,遇到一个问题:下载的时候如何又快又准确地记录下载的进度?

    缘由:记录下载进度是为了下次继续下载时做文件校验,比如有没有被篡改。

    目前的方案:(伪代码)

    while(true)

    {

    byte[] buffer = connection.read();

    file.write(buffer);

    database.save(file.length());

    }

    出现一个问题:

    如果不加 database.save ,下载速度可以达到正常的带宽速度。

    如果加了,下载速度就会慢,并且很明显。

    但是为了做校验,肯定需要 [实时] 保存下载的文件大小。

    我想用一个 tempValue [实时] 记录一下进度,最后再刷到数据库中。

    但是有个问题:如果程序异常终止,就会导致 tempValue 没有被刷到数据库中。

    这样的话,有什么比较好的解决方案??

    14 条回复    2016-10-14 10:03:11 +08:00
    bigboyq
        1
    bigboyq  
       2016-10-13 10:17:00 +08:00 via iPhone
    亲,你这个肯定会慢,因为 database save 方法被频繁调用,而且是 block 的,如果你把 database save 异步就不会影响,或者定量写入,比如 1MB 写一次,也会降低影响。
    异常的问题可以通过异常处理模块补充。
    814084764
        2
    814084764  
    OP
       2016-10-13 10:28:00 +08:00
    @bigboyq 异常的地方肯定有很多,除了下载模块的异常,还有其他模块的异常,如何去做补充?
    做一个全局的接收异常的方法?有些未捕获到的异常,又怎么处理呢?
    所以感觉异常这块的处理还是有点麻烦呢。。。束手无策的赶脚。
    要不就是改成写入到轻量级的文件中?
    Karblue
        3
    Karblue  
       2016-10-13 13:31:06 +08:00
    不要写完就刷新硬盘。 IO 操作是很费时间的。存到缓存。然后再把缓存定时写出。
    例如:把文件数据暂时存在全局变量中。开单独的线程去写出全局变量的文件
    lrh3321
        4
    lrh3321  
       2016-10-13 13:44:03 +08:00
    不支持 Linux ,我还是继续用 命令行吧
    lrh3321
        5
    lrh3321  
       2016-10-13 13:45:46 +08:00
    回错了,要回另外个帖子的。
    ===============
    我觉得做个几 MB 的缓存,满了再写入磁盘。丢数据也就是丢缓存里这几 MB
    limhiaoing
        6
    limhiaoing  
       2016-10-13 13:46:30 +08:00 via iPhone
    个人观点这个方法不可行。
    可以这么做,数据库记录已下载大小和 hash ,先写下载的数据到磁盘后记录下载进度和 hash 。
    limhiaoing
        7
    limhiaoing  
       2016-10-13 13:49:58 +08:00 via iPhone
    这样既是异常终止在写完下载数据和记录下载进度之间也不要紧,根据上次记录的下载进度丢弃多余的数据,校验记录的 hash 即可。
    limhiaoing
        8
    limhiaoing  
       2016-10-13 13:51:35 +08:00 via iPhone
    我估计迅雷的断点续传是用类似的方法,不过因为它是分块下载,所以 hash 应该也是分块计算的。
    ryd994
        9
    ryd994  
       2016-10-13 14:46:24 +08:00
    其实简单办法就是检查当前文件大小
    直接从那个长度开始
    这也是 wget 的做法
    至于校验数据完整性……除非重新下一遍,否则 http 协议本身不含 checksum 做不到
    bigboyq
        10
    bigboyq  
       2016-10-13 18:36:40 +08:00 via iPhone
    再起一个线程做 database.save 就好了,但是你又回来这里问数据库 update 慢怎么办。。。。。。
    icedx
        11
    icedx  
       2016-10-13 18:56:18 +08:00 via Android
    别说我不友善啊
    你是不是 SS
    database.save(file.length());
    你这样能不慢么
    dlllcs
        12
    dlllcs  
       2016-10-13 22:35:50 +08:00
    我觉得可以新建一个 Buffer ,大小差不多 32M 这样,每下载 32M 或者达到了 5 秒钟,就刷新进文件,这样比较好吧,这样 IO 比较少,而且丢数据也就丢最近几秒钟的数据
    limhiaoing
        13
    limhiaoing  
       2016-10-13 23:00:08 +08:00
    单单靠文件长度来判断文件是否被篡改是不可靠的,文本被篡改不一定会导致文件长度改变。
    即使你这两句之间没有可能抛出异常,但是断电呢?
    file.write(buffer);
    database.save(file.length());
    所以,记录文件长度只能用于丢弃多余的数据,而不能用来校验文件是否被篡改。
    用 hash+长度来记录已下载的文件就不需要实时的去保存长度了。可以每下载 10MB 保存一次,这样如果进程异常结束,最多就是丢弃 10MB 的数据。
    814084764
        14
    814084764  
    OP
       2016-10-14 10:03:11 +08:00
    @icedx 是有点傻。。哈哈
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2702 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 09:51 PVG 17:51 LAX 02:51 JFK 05:51
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86