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.

97 lines
1.7 KiB

package main
import (
"bufio"
"bytes"
"fmt"
"io"
"log"
"mime"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
)
func main() {
ReadAndDownload(".", os.Stdin)
}
func ReadAndDownload(root string, r io.Reader) {
var n int
var name string
scanner := bufio.NewScanner(r)
for scanner.Scan() {
txt := scanner.Text()
if name == "" || txt == "" {
name = txt
n = 0
continue
}
err := download(n, root, name, txt)
if err != nil {
log.Println(err)
}
n++
}
}
func download(n int, root, name, uri string) error {
u, err := url.Parse(uri)
if err != nil {
return fmt.Errorf("parsing uri %s: %v", uri, err)
}
ext := filepath.Ext(u.Path)
response, err := http.Get(uri)
switch {
case err != nil:
return fmt.Errorf("downloading file %s: %v", uri, err)
case response.StatusCode != http.StatusOK:
return fmt.Errorf("downloading file %s: status code %d", uri, response.StatusCode)
default:
defer response.Body.Close()
}
var r io.Reader = response.Body
if ext == "" {
var err error
ext, r, err = guessExt(response.Body)
if err != nil {
return err
}
}
filename := filepath.Join(root, name+strconv.Itoa(n)+ext)
f, err := os.Create(filename)
if err != nil {
return err
}
_, err = io.Copy(f, r)
return err
}
func guessExt(r io.Reader) (string, io.Reader, error) {
head, headCopy := make([]byte, 512), make([]byte, 512)
n, readErr := io.ReadFull(r, head)
head = head[:n]
copy(headCopy, head)
hr := bytes.NewReader(headCopy)
t := http.DetectContentType(head)
ext, err := mime.ExtensionsByType(t)
if readErr == io.EOF || readErr == io.ErrUnexpectedEOF {
return ext[0], hr, nil
}
if err != nil {
return "", nil, err
}
return ext[0], io.MultiReader(hr, r), nil
}