github.com/peterdeka/grab@v2.0.0+incompatible/cmd/grab/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/cavaliercoder/grab"
     9  )
    10  
    11  var (
    12  	inProgress = 0
    13  	failed     = 0
    14  	succeeded  = 0
    15  )
    16  
    17  func main() {
    18  	// validate command args
    19  	if len(os.Args) < 2 {
    20  		fmt.Fprintf(os.Stderr, "usage: %s [url]...\n", os.Args[0])
    21  		os.Exit(1)
    22  	}
    23  	urls := os.Args[1:]
    24  
    25  	// start file downloads, 3 at a time
    26  	fmt.Printf("Downloading %d files...\n", len(urls))
    27  	respch, err := grab.GetBatch(3, ".", urls...)
    28  	if err != nil {
    29  		fmt.Fprintf(os.Stderr, "%v\n", err)
    30  		os.Exit(1)
    31  	}
    32  
    33  	// monitor downloads
    34  	responses := make([]*grab.Response, 0, len(urls))
    35  	t := time.NewTicker(200 * time.Millisecond)
    36  	defer t.Stop()
    37  
    38  Loop:
    39  	for {
    40  		select {
    41  		case resp := <-respch:
    42  			if resp != nil {
    43  				// a new response has been received and has started downloading
    44  				responses = append(responses, resp)
    45  			} else {
    46  				// channel is closed - all downloads are complete
    47  				updateUI(responses)
    48  				break Loop
    49  			}
    50  
    51  		case <-t.C:
    52  			// update UI every 200ms
    53  			updateUI(responses)
    54  		}
    55  	}
    56  
    57  	fmt.Printf(
    58  		"Finished %d successful, %d failed, %d incomplete.\n",
    59  		succeeded,
    60  		failed,
    61  		inProgress)
    62  
    63  	// return the number of failed downloads as exit code
    64  	os.Exit(failed)
    65  }
    66  
    67  // updateUI prints the progress of all downloads to the terminal
    68  func updateUI(responses []*grab.Response) {
    69  	// clear lines for incomplete downloads
    70  	if inProgress > 0 {
    71  		fmt.Printf("\033[%dA\033[K", inProgress)
    72  	}
    73  
    74  	// print newly completed downloads
    75  	for i, resp := range responses {
    76  		if resp != nil && resp.IsComplete() {
    77  			if resp.Err() != nil {
    78  				failed++
    79  				fmt.Fprintf(os.Stderr, "Error downloading %s: %v\n",
    80  					resp.Request.URL(),
    81  					resp.Err())
    82  			} else {
    83  				succeeded++
    84  				fmt.Printf("Finished %s %d / %d bytes (%d%%)\n",
    85  					resp.Filename,
    86  					resp.BytesComplete(),
    87  					resp.Size,
    88  					int(100*resp.Progress()))
    89  			}
    90  			responses[i] = nil
    91  		}
    92  	}
    93  
    94  	// print progress for incomplete downloads
    95  	inProgress = 0
    96  	for _, resp := range responses {
    97  		if resp != nil {
    98  			fmt.Printf("Downloading %s %d / %d bytes (%d%%) - %.02fKBp/s ETA: %ds \033[K\n",
    99  				resp.Filename,
   100  				resp.BytesComplete(),
   101  				resp.Size,
   102  				int(100*resp.Progress()),
   103  				resp.BytesPerSecond()/1024,
   104  				int64(resp.ETA().Sub(time.Now()).Seconds()))
   105  			inProgress++
   106  		}
   107  	}
   108  }