I am new to Go
and trying to make a cross-browser app which can download multiple url's with progress bar. The Grab
package does the job nicely as shown in the example below. Now, I want to have a self-contained/portable/single-executable Web-UI which can display the download progress from the below code in a web-browser?
package main
import (
"fmt"
"github.com/cavaliercoder/grab"
"os"
"time"
)
func main() {
// get URL to download from command args
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "usage: %s url [url]...
", os.Args[0])
os.Exit(1)
}
urls := os.Args[1:]
// start file downloads, 3 at a time
fmt.Printf("Downloading %d files...
", len(urls))
respch, err := grab.GetBatch(3, ".", urls...)
if err != nil {
fmt.Fprintf(os.Stderr, "%v
", err)
os.Exit(1)
}
// start a ticker to update progress every 200ms
t := time.NewTicker(200 * time.Millisecond)
// monitor downloads
completed := 0
inProgress := 0
responses := make([]*grab.Response, 0)
for completed < len(urls) {
select {
case resp := <-respch:
// a new response has been received and has started downloading
// (nil is received once, when the channel is closed by grab)
if resp != nil {
responses = append(responses, resp)
}
case <-t.C:
// clear lines
if inProgress > 0 {
fmt.Printf("\033[%dA\033[K", inProgress)
}
// update completed downloads
for i, resp := range responses {
if resp != nil && resp.IsComplete() {
// print final result
if resp.Error != nil {
fmt.Fprintf(os.Stderr, "Error downloading %s: %v
", resp.Request.URL(), resp.Error)
} else {
fmt.Printf("Finished %s %d / %d bytes (%d%%)
", resp.Filename, resp.BytesTransferred(), resp.Size, int(100*resp.Progress()))
}
// mark completed
responses[i] = nil
completed++
}
}
// update downloads in progress
inProgress = 0
for _, resp := range responses {
if resp != nil {
inProgress++
fmt.Printf("Downloading %s %d / %d bytes (%d%%)\033[K
", resp.Filename, resp.BytesTransferred(), resp.Size, int(100*resp.Progress()))
}
}
}
}
t.Stop()
fmt.Printf("%d files successfully downloaded.
", len(urls))
}