LoginSignup
0
1

More than 5 years have passed since last update.

Goでファイルのバルクダウンロード

Posted at

GoでHTTPリクエストでファイルをバルクダウンロードするスニペット

仕様

ダウンロードするファイルのURL一覧を渡すと、発生したエラー回数を返す。

  • downloadの際に、エラーが発生した際のリトライ回数の制御: maxAttempts
  • サーバーへの同時接続数をセマフォで制御: maxConcurrents

コード

package download

import (
    "io"
    "log"
    "net/http"
    "os"
    "path"
    "sync"
    "sync/atomic"
)

const (
    maxConcurrents = 64
    maxAttempts    = 4
)

var output = "path/to/dir"

func Do(list []string) int64 {
    var wg sync.WaitGroup
    var sem = make(chan struct{}, maxConcurrents)

    var errCounts int64
    for _, v := range list {
        wg.Add(1)
        go func(target string) {
            defer wg.Done()

            var err error
            for i := 0; i < maxAttempts; i++ {
                sem <- struct{}{}
                err = download(target)
                <-sem
                if err == nil {
                    break
                }
            }
            if err != nil {
                atomic.AddInt64(&errCounts, 1)
                log.Printf("Failed to download: %s", err)
            }
        }(v)
    }
    wg.Wait()

    return errCounts
}

func download(target string) error {
    resp, err := http.Get(target)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    _, fileName := path.Split(target)
    file, err := os.Create(path.Join(output, fileName))
    if err != nil {
        return err
    }

    _, err = io.Copy(file, resp.Body)
    if closeErr := file.Close(); err == nil {
        err = closeErr
    }
    return err
}

制御出来ていないところ

  • httpクライアントを変更できない。
  • goroutineの数は、maxConcurrents以上に増える。
    c.f. http://blog.kaneshin.co/entry/2016/08/18/190435

  • ステータスコード毎のリトライロジック。

    • 4xx (Client Error)が返ってきた際は、リトライせずにスキップ
    • 5xx が返ってきた際は、Back-offを設定出来るとより良い

おまけ

簡易的には上のスニペットで、問題ないかと思いますが、
上記の3点もカバーした、worker型でファイルダウンロードするライブラリも書きました。
https://github.com/yyoshiki41/parallel-dl

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1