commit
4756ffad63
4 changed files with 168 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||||
|
module gitea.beetbox.io/Alex/odl |
||||
|
|
||||
|
go 1.18 |
@ -0,0 +1,102 @@ |
|||||
|
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 |
||||
|
} |
@ -0,0 +1,62 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"net/http" |
||||
|
"net/http/httptest" |
||||
|
"strings" |
||||
|
"testing" |
||||
|
"os" |
||||
|
"testing/fstest" |
||||
|
) |
||||
|
|
||||
|
var fs = http.FileServer(http.Dir("./testdata")) |
||||
|
|
||||
|
var srv = httptest.NewServer(fs) |
||||
|
|
||||
|
func TestDownload(t *testing.T) { |
||||
|
var ( |
||||
|
b bytes.Buffer |
||||
|
c = make(chan request) |
||||
|
) |
||||
|
|
||||
|
url := srv.URL + "/somefile" |
||||
|
t.Logf("file URL: %s", url) |
||||
|
|
||||
|
go func() { c <- request{&b, url}; close(c) }() |
||||
|
Download(c) |
||||
|
|
||||
|
want := "somefile inner data" |
||||
|
if got := b.String(); got != want { |
||||
|
t.Errorf("file buffer received unexpected value\nGot:\n%s\nWant:\n%s", got, want) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func TestRead(t *testing.T) { |
||||
|
input := `boston |
||||
|
http://localhost/someboston
|
||||
|
http://localhost/anotherboston.mp4
|
||||
|
http://localhost/finalboston.jpg
|
||||
|
|
||||
|
orlando |
||||
|
http://localhost/someorlando.jpg
|
||||
|
` |
||||
|
dir := t.TempDir() |
||||
|
t.Logf("root directory: %s", dir) |
||||
|
|
||||
|
c := Read(dir, strings.NewReader(input)) |
||||
|
for range c { |
||||
|
} // drain the channel
|
||||
|
|
||||
|
err := fstest.TestFS( |
||||
|
os.DirFS(dir), |
||||
|
"boston0", |
||||
|
"boston1.mp4", |
||||
|
"boston2.jpg", |
||||
|
"orlando0.jpg", |
||||
|
) |
||||
|
|
||||
|
if err != nil { |
||||
|
t.Fatal(err) |
||||
|
} |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
somefile inner data |
Loading…
Reference in new issue