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