go实现并发文件传输,断点续传

1: 概述

很多文件基本都是多协程下载文件要么就只有单协程的断点续传,这里给大家写一个支持有进度条的多协程下载文件,也支持断点续传

2: 使用示例代码

 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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package main

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"sync"

	"github.com/qianlnk/pgbar"
)

/**
* 需求:
1. 多协程并发下载文件
2. 断点续连
**/
func main() {
	//获取要下载文件
	DownloadFileName := "./Charles.4.5.6.zip"
	//copy的文件
	copyFileName := "./test.zip"
	storgeFileName := "./downloadRate.txt"
	//打开文件
	sfile, err := os.Open(DownloadFileName)
	if err != nil {
		panic(err)
	}
	defer sfile.Close()
	//获取文件大小
	info, _ := sfile.Stat()
	downloadSize := info.Size()
	var scount int64 = 1
	if downloadSize%5 == 0 {
		scount *= 5
	} else {
		scount *= 10
	}
	//分给每个协程的大小
	si := downloadSize / scount
	fmt.Printf("文件总大小:%v, 分片数:%v,每个分片大小:%v\n", downloadSize, scount, si)
	//open copy file
	copyFile, err := os.OpenFile(copyFileName, os.O_CREATE|os.O_WRONLY, os.ModePerm)
	if err != nil {
		panic(err)
	}
	storgeFile, err := os.OpenFile(storgeFileName, os.O_CREATE|os.O_RDWR, os.ModePerm)
	if err != nil {
		panic(err)
	}
	defer copyFile.Close()

	var currentIndex int64 = 0
	wg := sync.WaitGroup{}
	fmt.Println("文件下载进度条...")
	pgb := pgbar.New("")
	for ; currentIndex < scount; currentIndex++ {
		wg.Add(1)
		go func(current int64) {
			p := pgb.NewBar(fmt.Sprintf("%02d", (current+1))+"st", int(si))
			p.SetSpeedSection(900, 100)
			b := make([]byte, 10240)
			bs := make([]byte, 16)
			currentIndex, _ := storgeFile.ReadAt(bs, current*16)
			//取出所有整数
			reg := regexp.MustCompile(`\d+`)
			countStr := reg.FindString(string(bs[:currentIndex]))
			total, _ := strconv.ParseInt(countStr, 10, 0)
			progressBar := 1
			for {
				if total >= si {
					wg.Done()
					break
				}
				//从指定位置开始读
				n, err := sfile.ReadAt(b, current*si+total)
				if err == io.EOF {
					wg.Done()
					break
				}
				//从指定位置开始写
				copyFile.WriteAt(b, current*si+total)
				storgeFile.WriteAt([]byte(strconv.FormatInt(total, 10)+" "), current*16)
				total += int64(n)
				if total >= si/10*int64(progressBar) {
					progressBar += 1
					p.Add(int(si / 10))
				}
			}

		}(currentIndex)
	}
	wg.Wait()
	storgeFile.Close()
	os.Remove(storgeFileName)
	fmt.Printf("\n下载完成...\n")
}