/* uploader -- simplest form file uploader Copyright (C) 2018 Sergey Matveev */ package main import ( "bufio" "encoding/hex" "flag" "fmt" "io" "log" "net" "net/http" "os" "time" "golang.org/x/crypto/blake2s" "golang.org/x/net/netutil" ) const ( WriteBufSize = 1 << 20 ) func upload(w http.ResponseWriter, r *http.Request) { log.Println(r.RemoteAddr, "connected") if r.Method == http.MethodGet { w.Write([]byte(` Upload
`)) return } mr, err := r.MultipartReader() if err != nil { log.Println(r.RemoteAddr, err) return } p, err := mr.NextPart() if err != nil { log.Println(r.RemoteAddr, err) return } if p.FormName() != "fileupload" { log.Println(r.RemoteAddr, "non file form field") return } fn := time.Now().Format(time.RFC3339Nano) fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE, 0600) if err != nil { log.Println(r.RemoteAddr, fn, p.FileName(), err) return } defer fd.Close() h, err := blake2s.New256(nil) if err != nil { panic(err) } fdBuf := bufio.NewWriterSize(fd, WriteBufSize) mw := io.MultiWriter(fdBuf, h) n, err := io.Copy(mw, p) if err != nil { log.Println(r.RemoteAddr, fn, p.FileName(), err) return } if err = fdBuf.Flush(); err != nil { log.Println(r.RemoteAddr, fn, p.FileName(), err) return } sum := hex.EncodeToString(h.Sum(nil)) fmt.Fprintf(w, "bytes: %d\nBLAKE2s: %s\n", n, sum) log.Println(r.RemoteAddr, fn, p.FileName(), n, sum) } func main() { bind := flag.String("bind", "[::]:8086", "Address to bind to") conns := flag.Int("conns", 2, "Maximal number of connections") flag.Parse() ln, err := net.Listen("tcp", *bind) if err != nil { panic(err) } log.Println("listening", *bind) ln = netutil.LimitListener(ln, *conns) s := &http.Server{ ReadHeaderTimeout: 10 * time.Second, MaxHeaderBytes: 10 * (1 << 10), } http.HandleFunc("/upload/", upload) s.Serve(ln) }