package main import ( "fmt" "io" "net/http" "time" "github.com/gorilla/mux" ) func gameDownloader(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) game := vars["game"] Lib.Lock() g, ok := Lib.Games[game] Lib.Unlock() if !ok { Logger.Printf("Missing: %s", game) http.Error(w, "Game is missing", 404) return } w.Header().Add("Content-type", "application/tar") w.Header().Add("Estimated-size", fmt.Sprintf("%d", g.Size)) Logger.Printf("Client %s is downloading: %s", r.RemoteAddr, game) // Invert the writer so we can break up the copy and get progress // information in here rdr, pwrtr := io.Pipe() go func() { err := g.Package(pwrtr) if err != nil { Logger.Println("Error in package writing: ", err) } }() var total int64 start := time.Now() for { n, err := io.CopyN(w, rdr, 256*1024*1024) if err == io.EOF { break } if err != nil { Logger.Printf("Client %s Error Sending game: %s", r.RemoteAddr, err) // Headers already sent, don't bother sending an error return } total += n mb := float64(total / 1024 / 1024) rate := mb / time.Since(start).Seconds() Logger.Printf("Client %s is downloading %s: %0.1f%% done %.2f mb/s", r.RemoteAddr, game, float64(total)/float64(g.Size)*100, rate) } Logger.Printf("Client %s finished downloading: %s", r.RemoteAddr, game) }