ordered downloader
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
1.6 KiB

package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
)
func main() {
flag.Parse()
var err error
f := os.Stdin
filename := flag.Arg(0)
if filename != "-" && filename != "" {
f, err = os.Open(filename)
if err != nil {
log.Fatalf("failed to open file %s: %v", filename, err)
}
}
Download(Read(".", f))
}
type request struct {
w io.Writer
url string
}
func Download(c <-chan request) {
dl := func(w io.Writer, url string) error {
response, err := http.Get(url)
if err != nil {
return fmt.Errorf("downloading file %s: %v", url, err)
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code for %s: %d", url, response.StatusCode)
}
_, err = io.Copy(w, response.Body)
return err
}
for r := range c {
if err := dl(r.w, r.url); err != nil {
log.Println(err)
}
}
}
func Read(root string, r io.Reader) <-chan request {
scanner := bufio.NewScanner(r)
var n int
var name string
c := make(chan request)
create := func(name, uri string, n int) (io.Writer, error) {
var f io.Writer
u, err := url.Parse(uri)
if err != nil {
return f, fmt.Errorf("parsing url %s: %v", uri, err)
}
filename := filepath.Join(root, name+strconv.Itoa(n)+filepath.Ext(u.Path))
return os.Create(filename)
}
go func() {
for scanner.Scan() {
txt := scanner.Text()
if name == "" || txt == "" {
name = txt
n = 0
continue
}
f, err := create(name, txt, n)
if err != nil {
log.Println(err)
continue
}
c <- request{w: f, url: txt}
n++
}
close(c)
}()
return c
}