···44 "fmt"
55 "log"
66 "os"
77+ "time"
7889 "github.com/cuducos/chunk"
1010+ "github.com/spf13/cobra"
911)
10121111-func main() {
1212- chunk := chunk.DefaultDownloader()
1313- prog := newProgress()
1414- for status := range chunk.Download(os.Args[1:len(os.Args)]...) {
1515- if status.Error != nil {
1616- log.Fatal(status.Error)
1313+var rootCmd = &cobra.Command{
1414+ Use: "chunk",
1515+ Short: "Download tool for slow and unstable servers",
1616+ Long: `The idea of the project emerged as it was difficult for Minha Receita to handle the download of 37 files that adds up to just approx. 5Gb. Most of the download solutions out there (e.g. got) seem to be prepared for downloading large files, not for downloading from slow and unstable servers — which is the case at hand.`,
1717+ Run: func(cmd *cobra.Command, args []string) {
1818+ chunk := chunk.DefaultDownloader()
1919+ chunk.TimeoutPerChunk = timeoutChunk
2020+ chunk.MaxParallelDownloadsPerServer = concurrencyPerServer
2121+ chunk.MaxRetriesPerChunk = maxRetriesChunk
2222+ chunk.WaitBetweenRetries = waitBetweenRetries
2323+ chunk.ChunkSize = chunkSize
2424+ prog := newProgress()
2525+ for status := range chunk.Download(os.Args[1:len(os.Args)]...) {
2626+ if status.Error != nil {
2727+ log.Fatal(status.Error)
2828+ }
2929+ prog.update(status)
1730 }
1818- prog.update(status)
3131+ fmt.Printf("\r%s\nDownloaded to: %s", prog.String(), os.TempDir())
3232+ },
3333+}
3434+3535+// Flags
3636+var (
3737+ timeoutChunk time.Duration
3838+ concurrencyPerServer int
3939+ maxRetriesChunk uint
4040+ chunkSize int64
4141+ waitBetweenRetries time.Duration
4242+)
4343+4444+func init() {
4545+ rootCmd.Flags().DurationVarP(&timeoutChunk, "timeout", "t", chunk.DefaultTimeoutPerChunk, "timeout for the download of each chunk from each URL.")
4646+ rootCmd.Flags().UintVarP(&maxRetriesChunk, "max-retries", "r", chunk.DefaultMaxRetriesPerChunk, "maximum number of retries for each chunk.")
4747+ rootCmd.Flags().DurationVarP(&waitBetweenRetries, "wait-between-retries", "w", chunk.DefaultWaitBetweenRetries, "pause before retrying an HTTP request that has failed.")
4848+ rootCmd.Flags().Int64VarP(&chunkSize, "chunk-size", "s", chunk.DefaultChunkSize, "maximum size of each HTTP request done using the content range header.")
4949+ rootCmd.Flags().IntVarP(&concurrencyPerServer, "concurrency-per-server", "c", chunk.DefaultMaxParallelDownloadsPerServer, "controls the max number of concurrent connections opened to the same server.")
5050+}
5151+5252+func main() {
5353+ if err := rootCmd.Execute(); err != nil {
5454+ fmt.Println(err)
5555+ os.Exit(1)
1956 }
2020- fmt.Printf("\r%s\nDownloaded to: %s", prog.String(), os.TempDir())
2157}
+5-6
downloader.go
···1919 DefaultMaxParallelDownloadsPerServer = 8
2020 DefaultMaxRetriesPerChunk = 5
2121 DefaultChunkSize = 8192
2222- DefaultWaitBetweenRetries = 0 * time.Minute
2222+ DefaultWaitBetweenRetries = 1 * time.Second
2323)
24242525// DownloadStatus is the data propagated via the channel sent back to the user
···6464 // the the download of every file).
6565 TimeoutPerChunk time.Duration
66666767- // MaxParallelDownloadsPerServer controls how many requests are sent in
6868- // parallel to the same server. If all the URLs are from the same server
6969- // this is the total of parallel requests. If the user is downloading files
7070- // from different servers (including different subdomains), this limit is
7171- // applied to each server idependently.
6767+ // MaxParallelDownloadsPerServer controls the max number of concurrent
6868+ // connections opened to the same server. If all the URLs are from the same
6969+ // server this is the total of concurrent connections. If the user is downloading
7070+ // files from different servers, this limit is applied to each server idependently.
7271 MaxParallelDownloadsPerServer int
73727473 // MaxRetriesPerChunk is the maximum amount of retries for each HTTP request