打印 上一主题 下一主题 利用cURL实现单个文件分多段同时下载,支持断点续传(修订版)

 
打印 上一主题 下一主题

利用cURL实现单个文件分多段同时下载,支持断点续传(修订版) [复制链接]

摘自 http://bbs.chinaunix.net/thread-917952-1-1.html

在ubuntu下测试通过, 适合在支持多线程下载的站点下载文件
可以配合flashgot在firefox中使用

用法:./mycurl url [referedUrl]
第一个参数url是要下载的文件的地址,第二个参数referedUrl是指需要参照的网址(一般不需要,有些网站,比如华军需要此参数)
例如:
./mycurl ftp://xx.xxx.xxx/xxx.rar
或者
./mycurl http://xx.xxx.xx/xxx.rar http://www.xxx.xxx/yy.htm

下面是代码:

#!/bin/bash
####################################################################
#
# Script for curl to support resumable multi-part download.
#
# Tested on Ubuntu
#

url=$1

# How many "parts" will the target file be divided into?
declare -i parts=5

read -ep "Please input the target directory: " targetdir
read -ep "Please input the outfile name: " outfile

[ -z "$targetdir" ] && targetdir="./"
cd $targetdir||exit 2

[ -z "$outfile" ] && outfile=`basename $1`

#Set the referer url
if [ -n "$2" ]; then
    refurl="-L -e $2"
else refurl=""
fi

length=`curl $refurl -s -I $url|grep Content-Length|tail -n 1|sed s/[^0-9]//g`

if [ -z "$length" ]; then
        echo "cann't get the length of the target file"
        exit 1
fi
let "length = $length"

#lsession is used to record how many bytes of each subpart should be downloaded
declare -i lsession=$(($length/$parts))

finished="false"

#Assume the available maximum connections on server can reach "parts" at first
maxconn=$parts

while true;
do

for (( i=1; i<=parts ; i=i+1 ))
do

#Array offsetold is used to record how many bytes have been downloaded of each subpart

    if [ -e $outfile$i ]; then
                offsetold[$i]=`ls -l $outfile$i|awk '{print $5}'`
        else offsetold[$i]=0
        fi
        let "offsetold[$i] = ${offsetold[$i]}"

done

curr=0

for (( i=1; i<=parts && maxconn>0; i=i+1 ))
do

        if [ $i -lt $parts ]; then
                if [ ${offsetold[$i]} -lt $lsession ]; then      
                        curl $refurl -r $(($curr+${offsetold[$i]}))-$(($curr+$lsession-1)) $url >> $outfile$i &
            maxconn=$(($maxconn-1))
                fi
        else
                if [ ${offsetold[$i]} -lt $(($length-$(($lsession*$(($parts-1)))))) ]; then
                        curl $refurl -r $(($curr+${offsetold[$i]}))- $url >> $outfile$i &
            maxconn=$(($maxconn-1))
                fi
        fi
              
        curr=$(($curr+$lsession))                     

done


#To wait for all curl processes to terminate.

wait

finished="true"
maxconn=0
for (( i=1; i<=parts; i=i+1 ))
do

#Array offsetnew is used to record how many bytes have been downloaded of each subpart

        if [ -e $outfile$i ]; then
                offsetnew[$i]=`ls -l $outfile$i|awk '{print $5}'`
        else offsetnew[$i]=0
        fi              
        let "offsetnew[$i] = ${offsetnew[$i]}"
        if [ $i -lt $parts ]; then
                if [ ${offsetnew[$i]} -lt $lsession ]; then
                        finished="false"
                fi
        else
                if [ ${offsetnew[$i]} -lt $(($length-$(($lsession*$(($parts-1)))))) ]; then
                        finished="false"
                fi
        fi

#Calculate the "real" available maximum connections supported by server

    if [ ${offsetnew[$i]} -gt ${offsetold[$i]} ]; then
        maxconn=$(($maxconn+1))   
    fi
done

        if [ "$finished" == "true" ]; then
                break
    elif [ $maxconn -eq 0 ]; then
        echo "Some errors may occur. retry 10 sec later..."
        sleep 10
        maxconn=parts
        fi
done

echo "All parts have been downloaded. Merging..."

mv --backup=t $outfile"1" $outfile
for (( i=2; i<=parts; i=i+1))
do
        cat $outfile$i >> $outfile
        rm $outfile$i
done

echo "Done."

[ 本帖最后由 ypxing 于 2007-4-4 21:45 编辑 ]

 
钢七连
不抛弃,不放弃
http://ypxing.cublog.cn/
   
   

家境小康

Rank: 2

帖子
1597
主题
14
精华
0
可用积分
1679
信誉积分
100
专家积分
0
在线时间
56 小时
注册时间
2004-12-13
最后登录
2011-04-28
论坛徽章:
0
2[报告]
 
发表于 2007-04-01 11:01:09 |只看该作者
支持一下,这个脚本实用价值很好(2004年到现在的第一帖……)。

提两个建议:
1. 接收curl的参数,这样才是一个完整的curl壳。
2. 等待本shell脚本所起的后台进程全部完成,用wait,既准确又简洁。
另外,随着您的shell功力提高,您可以自己尝试着修整该脚本,相信也会有所收获。

PS:有个真正的多线程(这个脚本是多进程下载)命令行下载工具axel,据说不错,但我没用过,可以一试。
 
SUN E4500/SUN F4800/SUN V880
Solaris 8
KSH/NAWK/SED/VIM 6.3.3/perl 5.005_03
   
 

家境小康

Rank: 2

帖子
1276
主题
40
精华
4
可用积分
1470
信誉积分
102
专家积分
130
在线时间
1 小时
注册时间
2004-11-19
最后登录
2012-06-22
论坛徽章:
0

3[报告]

 
发表于 2007-04-01 11:21:53 |只看该作者

回复 2楼 一梦如是 的帖子

谢谢大侠指点, 学习中...
俺也去试试axel
 

钢七连
不抛弃,不放弃
http://ypxing.cublog.cn/

 



大富大贵

Rank: 7Rank: 7Rank: 7

帖子
3040
主题
480
精华
1
可用积分
17274
信誉积分
1220
专家积分
5
在线时间
2434 小时
注册时间
2005-08-30
最后登录
2016-06-13
论坛徽章:
84
数据库技术版块每日发帖之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00每日论坛发贴之星
日期:2015-12-29 06:20:00程序设计版块每日发帖之星
日期:2016-01-03 06:20:00程序设计版块每月发帖之星
日期:2016-01-07 23:02:45
4[报告]
 
发表于 2007-04-01 11:23:22 |只看该作者
curl 没用过,不过这么好的想法,,顶一下!
 
慷慨陈词,岂能皆如人意,鞠躬尽瘁,但求无愧我心。
stay hungry, stay foolish
https://github.com/tcler
http://www.tldp.org/LDP/abs/html
   
 

丰衣足食

Rank: 1

帖子
8343
主题
245
精华
1
可用积分
726
信誉积分
195
专家积分
15
在线时间
411 小时
注册时间
2006-09-18
最后登录
2013-08-16
论坛徽章:
0

5[报告]

 
发表于 2007-04-01 14:21:48 |只看该作者
哇,支持!
 

爱家、爱国、爱和平、爱自由、爱生活、爱大自然!

 



丰衣足食

Rank: 1

帖子
154
主题
17
精华
0
可用积分
748
信誉积分
238
专家积分
0
在线时间
76 小时
注册时间
2005-04-01
最后登录
2016-06-06
论坛徽章:
0
6[报告]
 
发表于 2007-04-01 19:28:31 |只看该作者
顶,佩服+羡慕楼主

我的习惯是下大文件用wget,小文件直接用firefox的下载器,有的站点单线程不快的话,就无能为力了
 
   
 

家境小康

Rank: 2

帖子
1276
主题
40
精华
4
可用积分
1470
信誉积分
102
专家积分
130
在线时间
1 小时
注册时间
2004-11-19
最后登录
2012-06-22
论坛徽章:
0

7[报告]

 
发表于 2007-04-01 21:50:06 |只看该作者
一开始写这个script是为了和flashgot配合,在firefox里使用来者,呵呵
我也经常用wget的



原帖由 mmx384 于 2007-4-1 19:28 发表
顶,佩服+羡慕楼主

我的习惯是下大文件用wget,小文件直接用firefox的下载器,有的站点单线程不快的话,就无能为力了
 

钢七连
不抛弃,不放弃
http://ypxing.cublog.cn/

 



家境小康

Rank: 2

帖子
792
主题
43
精华
0
可用积分
1714
信誉积分
172
专家积分
0
在线时间
101 小时
注册时间
2004-03-14
最后登录
2013-09-28
论坛徽章:
0
8[报告]
 
发表于 2007-04-01 23:38:42 |只看该作者
ASUSW3Z-W3HT30; DELL Lattitude D630; ThinkPadX61 7675C ; DELL OPTIPLEX-755
   
 

家境小康

Rank: 2

帖子
1276
主题
40
精华
4
可用积分
1470
信誉积分
102
专家积分
130
在线时间
1 小时
注册时间
2004-11-19
最后登录
2012-06-22
论坛徽章:
0

9[报告]

 
发表于 2007-04-02 11:09:10 |只看该作者
谢谢
用他们提供的库可以开发更友好,功能更复杂的东东,有时间要试一下的

原帖由 baif 于 2007-4-1 23:38 发表
http://pycurl.sourceforge.net/
 

钢七连
不抛弃,不放弃
http://ypxing.cublog.cn/

 



家境小康

Rank: 2

帖子
1276
主题
40
精华
4
可用积分
1470
信誉积分
102
专家积分
130
在线时间
1 小时
注册时间
2004-11-19
最后登录
2012-06-22
论坛徽章:
0
10[报告]
 
发表于 2007-04-03 21:28:23 |只看该作者
修改了一下原来的脚本
1. 用wait等待后台进程的完成
2. 避免了对不支持多线程下载的站点多次重复连接

通过修改写过的脚本确实可以学到更多东西

原帖由 一梦如是 于 2007-4-1 11:01 发表
支持一下,这个脚本实用价值很好(2004年到现在的第一帖……)。

提两个建议:
1. 接收curl的参数,这样才是一个完整的curl壳。
2. 等待本shell脚本所起的后台进程全部完成,用wait,既准确又简洁。
另外, ...
 
钢七连
不抛弃,不放弃
http://ypxing.cublog.cn/
原文地址:https://www.cnblogs.com/LiuYanYGZ/p/5603866.html