您可以为FileSystem 的实现提供FileServer 的进度计数器。
例子:
package main
import (
"net/http"
)
type fileWithProgress struct {
http.File
size int64
downloaded int64
lastReported int64
name string
client string
}
func (f *fileWithProgress) Read(p []byte) (n int, err error) {
n, err = f.File.Read(p)
f.downloaded += int64(n)
f.lastReported += int64(n)
if f.lastReported > 1_000_000 { // report every 1e6 bytes
println("client:", f.client, "file:", f.name, "downloaded:", f.downloaded*100/f.size, "%")
f.lastReported = 0
}
return n, err
}
func (f *fileWithProgress) Seek(offset int64, whence int) (int64, error) {
f.downloaded = 0 // reset content detection read if no content-type specified
return f.File.Seek(offset, whence)
}
func (f *fileWithProgress) Close() error {
println("client:", f.client, "file:", f.name, "done", f.downloaded, "of", f.size, "bytes")
return f.File.Close()
}
type dirWithProgress struct {
http.FileSystem
client string
}
func (d *dirWithProgress) Open(name string) (http.File, error) {
println("open:", name, "for the client:", d.client)
f, err := d.FileSystem.Open(name)
if err != nil {
return nil, err
}
st, err := f.Stat()
if err != nil {
return nil, err
}
return &fileWithProgress{File: f, size: st.Size(), name: st.Name(), client: d.client}, nil
}
func fileServer(fs http.FileSystem) http.Handler {
f := func(w http.ResponseWriter, r *http.Request) {
progressDir := dirWithProgress{FileSystem: fs, client: r.RemoteAddr}
http.FileServer(&progressDir).ServeHTTP(w, r)
}
return http.HandlerFunc(f)
}
func main() {
dir := http.Dir(".")
fs := fileServer(dir)
http.Handle("/", fs)
http.ListenAndServe("127.0.0.1:8080", nil)
}