天天看點

golang協程分段下載下傳檔案

/*
*
* 需求:
1. 多協程下載下傳檔案
2.斷點續連
*
*/
func Coprogram(c *gin.Context) {
   //擷取要下載下傳檔案
   DownloadFileName := "./123.zip"
   //copy的檔案
   copyFileName := "./test.zip"
   storgeFileName := "./current.txt"
   //打開檔案
   sfile, err := os.Open(DownloadFileName)
   if err != nil {
      fmt.Println(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 {
      fmt.Println(err)
   }
   storgeFile, err := os.OpenFile(storgeFileName, os.O_CREATE|os.O_RDWR, os.ModePerm)
   if err != nil {
      fmt.Println(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.Sprint((current+1))+"st", int(si))
         // p.SetSpeedSection(900, 100)
         b := make([]byte, 1024)
         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.Println("下載下傳完成")
}      

繼續閱讀