自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用 Go 語(yǔ)言開(kāi)發(fā)一個(gè)并發(fā)文件下載器

開(kāi)發(fā) 后端
Go 語(yǔ)言是一門(mén)了不起的語(yǔ)言,盡管它非常簡(jiǎn)單,與 Koltin 和 Scala 等其他現(xiàn)代語(yǔ)言相比,它的功能很少,但它具有強(qiáng)大的并發(fā)能力。這篇文章,我們將會(huì)看到使用 Go 語(yǔ)言如何編寫(xiě)一個(gè)完整的并發(fā)文件下載器。

[[421486]]

本文轉(zhuǎn)載自微信公眾號(hào)「Golang來(lái)啦」,作者Seekload。轉(zhuǎn)載本文請(qǐng)聯(lián)系Golang來(lái)啦公眾號(hào)。

今天給大家分享一個(gè)實(shí)戰(zhàn)項(xiàng)目,涉及到的知識(shí)點(diǎn)還挺多,文末也有源碼地址!!

原文如下:

Go 語(yǔ)言是一門(mén)了不起的語(yǔ)言,盡管它非常簡(jiǎn)單,與 Koltin 和 Scala 等其他現(xiàn)代語(yǔ)言相比,它的功能很少,但它具有強(qiáng)大的并發(fā)能力。這篇文章,我們將會(huì)看到使用 Go 語(yǔ)言如何編寫(xiě)一個(gè)完整的并發(fā)文件下載器。完整的代碼在這里[1]。

檢查服務(wù)器是否支持并發(fā)下載

如何之前使用過(guò)類(lèi)似 IDM 的下載工具,你可能會(huì)注意到它支持并發(fā)下載文件。

可以看到下載文件的時(shí)候啟動(dòng)了 8 個(gè)進(jìn)程。

實(shí)現(xiàn)并發(fā)下載,我們必須確保服務(wù)器支持范圍請(qǐng)求。怎么確認(rèn)呢?我們可以發(fā)送 HEAD 請(qǐng)求,如果響應(yīng)頭的 Accept-Ranges 返回的值是 bytes,我們就能確定服務(wù)器支持此功能。

  1. res, err := http.Head("http://some.domain/some.file"
  2. if err != nil { 
  3.    log.Fatal(err) 
  4.  
  5. if res.StatusCode == http.StatusOK && res.Header.Get("Accept-Ranges") == "bytes" { 
  6.    // Yeh, server supports partial request 

如何下載文件的其中一部分

設(shè)想服務(wù)器支持范圍請(qǐng)求,我們知道文件大小是 4000 字節(jié)(文件大小從響應(yīng)頭的 Content-Length 獲取)。要僅下載 2000 到 3000 字節(jié)的文件的一部分,我們可以發(fā)送 HTTP GET 請(qǐng)求,并在 header 頭設(shè)置 Range 參數(shù):

  1. curl -X GET -H "Range: bytes=2000-3000" -o OUTPUT_FILE http://some.domain/some.file 

實(shí)現(xiàn)相同功能的代碼如下:

  1. req, err := http.NewRequest("GET""http://some.domain/some.file", nil) 
  2. if err != nil { 
  3.     log.Fatal(err) 
  4. rangeStart := 2000 
  5. rangeStop := 3000 
  6. req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", rangeStart, rangeStop)) 
  7.  
  8. // make a request 
  9. res, err := http.DefaultClient.Do(req) 

將響應(yīng)保存在文件中

為了支持?jǐn)帱c(diǎn)續(xù)傳功能,我們不會(huì)將請(qǐng)求響應(yīng)保存在內(nèi)存里,而是會(huì)持久化在文件中。舉個(gè)例子,如果我們把并發(fā)級(jí)別設(shè)置成 4,在輸出目錄將會(huì)有 4 個(gè)臨時(shí)文件。下面的代碼,我們只是簡(jiǎn)單地讀取 HTTP 響應(yīng)體并將它寫(xiě)入一個(gè)文件中:

  1. f, err := os.OpenFile(outputPath, flags, 0644) 
  2.     if err != nil { 
  3.         log.Fatal(err) 
  4.     } 
  5. defer f.Close() 
  6.  
  7. _, err = io.Copy(f, res.Body) 

暫停下載

不知道大家注意到?jīng)]有,上面代碼有個(gè)問(wèn)題,使用時(shí)不支持 CTRL+C 暫停下載。如果下載的文件過(guò)大,或者網(wǎng)絡(luò)慢,下載需要花費(fèi)很長(zhǎng)時(shí)間。因?yàn)?io.Copy 復(fù)制文件時(shí)遇到 EOF 或者發(fā)生錯(cuò)誤才結(jié)束。為了解決這個(gè)問(wèn)題,我們使用 io.CopyN 和 cancel channel 組合:

  1. // copy to output file 
  2. for { 
  3.   select { 
  4.     case <- context.Done(): 
  5.        // user canceled the download 
  6.         return 
  7.     default
  8.       _, err = io.CopyN(f, res.Body, BUFFER_SIZE)) 
  9.       if err != nil { 
  10.         if err == io.EOF { 
  11.             return 
  12.         } else { 
  13.             log.Fatal(err) 
  14.         } 
  15.       } 
  16.     } 
  17.   } 

其他功能參見(jiàn)完整源代碼

這篇文章只提到了代碼中最重要的部分,但是通過(guò)閱讀代碼你可以了解其他功能是怎么實(shí)現(xiàn)的,比如:進(jìn)度條的工作方式、如何使用 sync 包實(shí)現(xiàn)部分下載的同步、如何合并臨時(shí)文件以及如何實(shí)現(xiàn)恢復(fù)功能等。所以可以通過(guò)閱讀倉(cāng)庫(kù)代碼[2]獲取更多信息。

參考資料

[1]這里: https://github.com/mostafa-asg/go-dl

[2]倉(cāng)庫(kù)代碼: https://github.com/mostafa-asg/go-dl

via:

https://returnfn.com/lets-build-a-concurrent-file-downloader-in-go

作者:Mostafa Asgari

 

責(zé)任編輯:武曉燕 來(lái)源: Golang來(lái)啦
相關(guān)推薦

2021-07-05 10:33:55

開(kāi)發(fā)技能Go

2023-04-03 06:53:04

Go開(kāi)發(fā)架構(gòu)

2024-05-09 10:26:14

2021-01-14 09:49:10

安全漏洞開(kāi)發(fā)

2022-01-05 08:58:08

Python解釋器編程語(yǔ)言

2015-10-12 15:50:07

PaaS云平臺(tái)開(kāi)發(fā)go

2021-02-25 22:17:19

開(kāi)發(fā)技術(shù)編程

2014-04-09 09:32:24

Go并發(fā)

2023-03-05 23:11:07

Go語(yǔ)言服務(wù)

2021-06-24 06:35:00

Go語(yǔ)言進(jìn)程

2017-11-14 11:12:50

Go語(yǔ)言編譯器

2019-07-05 08:39:39

GoSQL解析器

2024-01-08 13:40:00

并發(fā)安全? 數(shù)量

2021-07-30 07:28:15

WorkerPoolGo語(yǔ)言

2023-12-21 07:09:32

Go語(yǔ)言任務(wù)

2013-05-28 09:43:38

GoGo語(yǔ)言并發(fā)模式

2021-07-15 23:18:48

Go語(yǔ)言并發(fā)

2023-02-10 09:40:36

Go語(yǔ)言并發(fā)

2021-07-26 10:14:38

Go語(yǔ)言工具

2021-04-13 06:35:13

Elixir語(yǔ)言編程語(yǔ)言軟件開(kāi)發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)