title: Golang and local web-interface for download progress?
body: <p>I am new to <code>Go</code> and trying to make a cross-browser app which can download multiple url's with progress bar. The <code>Grab</code> 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?</p>
  
  <pre><code>package main
  
  import (
      "fmt"
      "github.com/cavaliercoder/grab"
      "os"
      "time"
  )
  
  func main() {
      // get URL to download from command args
      if len(os.Args) &lt; 2 {
          fmt.Fprintf(os.Stderr, "usage: %s url [url]...\n", os.Args[0])
          os.Exit(1)
      }
  
      urls := os.Args[1:]
  
      // start file downloads, 3 at a time
      fmt.Printf("Downloading %d files...\n", len(urls))
      respch, err := grab.GetBatch(3, ".", urls...)
      if err != nil {
          fmt.Fprintf(os.Stderr, "%v\n", 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 &lt; len(urls) {
          select {
          case resp := &lt;-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 &lt;-t.C:
              // clear lines
              if inProgress &gt; 0 {
                  fmt.Printf("\033[%dA\033[K", inProgress)
              }
  
              // update completed downloads
              for i, resp := range responses {
                  if resp != nil &amp;&amp; resp.IsComplete() {
                      // print final result
                      if resp.Error != nil {
                          fmt.Fprintf(os.Stderr, "Error downloading %s: %v\n", resp.Request.URL(), resp.Error)
                      } else {
                          fmt.Printf("Finished %s %d / %d bytes (%d%%)\n", 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\n", resp.Filename, resp.BytesTransferred(), resp.Size, int(100*resp.Progress()))
                  }
              }
          }
      }
  
      t.Stop()
  
      fmt.Printf("%d files successfully downloaded.\n", len(urls))
  }
  </code></pre>