Merhaba, Yabancı!

Burada yeni gibi görünüyorsunuz. Eğer katılmak istiyorsanız düğmelerden birine tıklayınız.

大量文件批量下载出现的错误及解决思路

About: Aria2下载助手

都是下载文件数量比较多时候出现的异常情况:

  1. 当文件比较大下载完成需要较长时间,且存在多个文件同时添加下载时,前几个文件下载都不会出错,但后面的文件在aria2中有可能出现无法下载错误,时间一般在添加任务到aria2一两个小时后,此时检查对应文件下载地址度盘会提示错误信息:
    { "error_code":31064, "error_msg":"xcode expire time out error" } ,应该是下载链接有效期较短过期了。这个要解决可能需要脚本后台和aria2通信定期查询刷新任务,会比较麻烦。当前手动解决方法就是失败后手动把相关文件再添加一次即可,aria2会自动续传跳过已完成的下载。

  2. 直接目录下载多文件时,当目录里面文件很多且还存在子目录时,会出现很多文件添加失败的情况,最新版中也加了这个的错误提示和失败的文件列表。
    一个可以重现的例子:比如主目录里面有上百个文件,里面还有个子目录也有几十个文件,直接下载主目录,就会出现这种错误。如果只是某个目录里面文件很多但没有子目录的文件则不会出现问题。
    因为现在获取文件下载地址的时候用的并发机制,文件数量很多时候短时间请求量较大可能被度盘识别而拒绝响应,可以考虑将当前的并发改成顺序执行,一个文件地址获取完成后再获取下一个文件的地址,模仿人工操作方式,就能解决问题且较难识别出来。
    改代码测试了下,改成顺序执行模式就没有部分文件无法获取地址的这个错误了。这样顺序执行后文件数较多时会需要一段时间才能获取到文件地址再提交到aria2开始下载,但因为是后台自动处理,只要不出错也问题不大,或者可以配合后面第3点的单文件地址解析后立即提交aria2下载也能避免这个等待。

  3. 在下载这种文件数量很多的情况时另外发现一个问题,aria2对单个请求的POST数据大小有限制,不能超过2M,改成顺序执行后能获取到下载地址了,但最后将地址提交到aria2的时候没有成功,jsonrpc请求无答复,任务也没添加上去。
    此时的POST数据其中有很大一部分是文件的下载地址重复了16次导致虚大,这个改成单地址配合split=16后aria2的请求数据低于2M就没有问题了,但如果文件数如果进一步增加到上千后仍可能出错,故可以考虑在前面第2点的顺序模式获取文件地址后,获得一个地址立即向aria2提交对应地址的文件下载请求,这样也能改善顺序模式下获取文件地址较慢aria2迟迟没有开始下载的问题。aria2的请求是本地进行,网络开销小请求次数多一些也没多少影响。

Yorumlar

  • 多谢指点。
    目前就麻烦的问题如何让用户掌握aira2的使用,有部分问题要解决则需要用户能熟练应用aria2来配合,包括上述提到的问题。
    因为有不少人是不来这边看看,直接发私信问,回复这些问题也占用大量时间。
    有些问题还非常让人尴尬,比如说浏览器安装很多扩展和脚本,而用户又不懂,解决起来相当费时费力。还有的人也很奇葩,比如有一个的问题是下载到一小半进度就失败了,我猜测问题可能是他用的aria2,建议他用我分享的那个,他又说他的那个更好不想换,大概意思是某个群专有的。那我也没法了,只好请他分享给我看看,不然我也弄不明白是咋回事,结果要我出钱才分享,我感觉自己都要疯了。

  • November 2019 düzenlendi Firefox

    是的,普通用户的问题有时候解决起来很费劲,常常缺乏信息就一句不行,需要花费很多时间,而且往往是用户自身的运行环境问题。所以代码上要尽量写的健壮,各种运行环境以及可能的异常都考虑到并处理好,牵扯到全局的一些命名之类用长一些的名字的尽量避免可能的冲突。UI方面的修改尽量减少,对原有页面的修改处可考虑用增加而非替换的方式去做尽量做到和原有环境的共存。另外再就是增加调试或日志信息,或者在必要之处多做一些提示,这样出现问题也比较容易诊断。

    看到今天新版的改动了,这种仍然采用并发模式,固定100毫秒间隔的模式我之前有做过测试,文件数一多后面部分的请求仍然可能会失败。估计你也是测试到这个问题所以加了128文件数的限制,不过这样就没法下载包含大量文件的文件夹了,另外这种模式就算只有128文件,遇到网络波动时,仍有可能出现部分文件异常的情况(先后发出的多次请求因为间隔很小,网络拥堵导致仍然接近同时到达)。

    并发模式如果将延迟进一步增大,到1000毫秒左右则基本不会出现请求异常了,但此时文件一多处理速度也很慢,还不如选用顺序模式。

    所以我之前的建议中换用了顺序模式,自己用下来效果不错,很稳定,包含文件数量很大的文件夹处理起来也没问题,暂时没有出现获取失败的情况。aria2 POST数据过大的问题也一并解决了,且获取到第一个文件地址即在aria2添加任务开始下载,实际速度比以前所有地址获取后再开始实际下载更快。当然顺序模式得等前一个请求答复后再做后一个请求,文件一多需要时间也比较长,所以再额外添加了进度百分比显示以及更多信息的提示( 提示文字鼠标移动到下载按钮上即可显示)。相关改动的代码如下,供参考(基于0.2.11.20191123版):

                                    /* 注释内为被替换的代码部分:
                                    f = setInterval(() => {
                                        if (t == o.length) {
                                            clearInterval(f);
                                            let e = [],
                                                t = [];
                                            o.forEach(o => {
                                                o.url.length ? e.push(o) : t.push(o.path)
                                            }), t.length && alert("\u4ee5\u4e0b\u6587\u4ef6\u56e0\u4e0d\u80fd\u4e0b\u8f7d\u800c\u5ffd\u7565\uff1a\n\n" + t.join("\r") + "\n\n\u5efa\u8bae\u5c1d\u8bd5\u7528\u5176\u4ed6\u8d26\u53f7\u6216\u8005\u5176\u4ed6\u65b9\u6cd5\u4e0b\u8f7d\u3002");
                                            e.length && u.aria2(e, ipod.aria2.jsonrpc), $("div.btn-group.outline > button[name=zydl] > i").attr("class", "fa-download")
                                        }
                                    }, 1e3);
                                o.length > 128 ? (o = [], alert("\u672c\u6b21\u52fe\u9009\u4e0b\u8f7d\u7684\u6587\u4ef6\u6570\u91cf\u8fc7\u591a\uff0c\u5efa\u8bae\u4f60\u5206\u6279\u52fe\u9009\u6587\u4ef6\u8fdb\u884c\u4e0b\u8f7d\u3002\n\u5982\u679c\u52fe\u9009\u7684\u6587\u4ef6\u5939\u4e2d\u542b\u6709\u5927\u91cf\u6587\u4ef6\u8bf7\u8fdb\u5165\u8be5\u6587\u4ef6\u5939\u5206\u6279\u4e0b\u8f7d\u3002\n\u77ed\u65f6\u95f4\u5185\u89e3\u6790\u8fc7\u591a\u7684\u4e0b\u8f7d\u5730\u5740\u5bb9\u6613\u88ab\u5ea6\u76d8\u4fa6\u6d4b\u5230\u4e14\u53ef\u80fd\u4f1a\u5bf9\u8d26\u53f7\u62c9\u9ed1\u3002")) : o.forEach(o => {
                                    e++, o.dir = ipod.aria2.dir;
                                    o.header = ipod.header, setTimeout(() => {
                                        GM_xmlhttpRequest({
                                            method: "HEAD",
                                            url: "https://pcs.baidu.com/rest/2.0/pcs/file?app_id=778750&method=download&path=" + encodeURIComponent(o.path),
                                            headers: ipod.header2,
                                            timeout: 5e3,
                                            onload(e) {
                                                if (t++, e.finalUrl)
                                                    for (let t = 0; 2 > t; t++) o.url.push(e.finalUrl)
                                            },
                                            ontimeout() {
                                                t++
                                            }
                                        })
                                    }, 100 * e)
                                })
                                */
                                function downloadFileList(fileList) {
                                    let currDownload = 0;                                   
                                    getNextFileURL();
    
                                    function checkDownloadResult() {
                                        let failList = [];
                                        fileList.forEach(item => {
                                            if (!item.url.length) failList.push(item.path);
                                        });
                                        if (failList.length) alert("以下文件因不能下载而忽略:\n\n" + failList.join("\r") + "\n\n建议尝试用其他账号或者其他方法下载。");
                                        $("div.btn-group.outline > button[name=zydl] > i").attr("class", "fa-download");
                                        setDownloadText("下载");
                                        setDownloadTooltip("获取完成,总计" + fileList.length + "文件," + failList.length + "失败。");
                                    }
    
                                    function setDownloadText(txt) {
                                        $("div.btn-group.outline > button[name=zydl]")[0].lastChild.nodeValue = " " + txt;
                                    }
    
                                    function setDownloadTooltip(txt) {
                                        $("div.btn-group.outline > button[name=zydl]").attr("title", txt);
                                    }
    
                                    function getNextFileURL() {
                                        setDownloadText(Math.floor(currDownload * 100/ fileList.length) + "%");
                                        setDownloadTooltip("获取中,进度 " + currDownload + "/" + fileList.length);
                                        if (currDownload < fileList.length) {
                                            let item = fileList[currDownload];
                                            setTimeout(() => {getFinalURL(item);}, 0);  //可增加设置项在每次请求后额外增加随机延迟避免检测,暂设0
                                            currDownload++;
                                        } else {
                                            checkDownloadResult();
                                        }
                                    }
    
                                    function getFinalURL(item) {
                                        if (!item) {
                                            getNextFileURL();
                                            return;
                                        }
                                        item.dir = ipod.aria2.dir, item.header = ipod.header;
    
                                        GM_xmlhttpRequest({
                                            method: "HEAD",
                                            url: "https://pcs.baidu.com/rest/2.0/pcs/file?app_id=778750&method=download&path=" + encodeURIComponent(item.path),
                                            headers: ipod.header2,
                                            timeout: 5e3,
                                            onload(response) {
                                                if (response.finalUrl) {
                                                    item.url.push(response.finalUrl);
                                                    u.aria2([item], ipod.aria2.jsonrpc);
                                                }
                                                getNextFileURL();
                                            },
                                            ontimeout: getNextFileURL,
                                            onerror: getNextFileURL,
                                            onabort: getNextFileURL
                                        });
                                    }
                                }
                                downloadFileList(o);
    
Yorum yapmak içinOturum Açın yada Kayıt Olun .