go局域网共享文件夹(静态文件服务)

package main

import (
	"fmt"
	"io/fs"
	"net"
	"net/http"
	"os"
	"path"
	"sort"
)

const (
	iconImg       = `D:\FileRecv\MobileFile\mmexport1641207943484.jpg`
	backgroundImg = `D:\FileRecv\MobileFile\Image\img157.png`
	head          = `
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon32.ico" type="image/x-icon"/>
<title>😁😁😁</title>
<style>
    body {
		font-family:Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
        background-image: url("/backgroundImg");
        background-size: cover;
    }
</style>
</head>
`
)

var (
	port = "80"
	dir  = `C:\迅雷下载`
)

type IconHandler struct {
}

func (i IconHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	http.ServeFile(writer, req, iconImg)
}

type ImgHandler struct {
}

func (i ImgHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	http.ServeFile(writer, req, backgroundImg)
}

type FileHandler struct {
	unit []string
}

func NewFileHandler() *FileHandler {
	return &FileHandler{unit: []string{"B", "KB", "MB", "GB", "TB"}}
}

func (f FileHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	p := path.Join(dir, req.URL.Path)
	file, err := os.Open(p)
	if err != nil {
		return
	}
	defer file.Close()
	info, _ := file.Stat()
	if info.IsDir() {
		f.listDir(writer, req, file)
	} else {
		http.ServeContent(writer, req, info.Name(), info.ModTime(), file)
	}
}

func (f FileHandler) formatSize(info fs.FileInfo) string {
	if info.IsDir() {
		return "-"
	}
	var size = float64(info.Size())
	for i := range f.unit {
		if size < 1024 {
			return fmt.Sprintf("%.2f%s", size, f.unit[i])
		}
		size /= 1024
	}
	return "-1"
}

type Writer struct {
	writer http.ResponseWriter
}

func NewWriter(writer http.ResponseWriter) *Writer {
	return &Writer{writer: writer}
}

func (w Writer) WriteF(format string, a ...any) {
	_, _ = fmt.Fprintf(w.writer, format, a...)
}

func (f FileHandler) listDir(writer http.ResponseWriter, req *http.Request, Dir http.File) {
	files, err := Dir.Readdir(-1)
	if err != nil {
		return
	}
	sort.Slice(files, func(i, j int) bool {
		if files[i].IsDir() && !files[j].IsDir() {
			return true
		}
		return false
	})
	w := NewWriter(writer)
	w.WriteF(`<html>`)
	w.WriteF(head)
	w.WriteF(`<body>`)
	w.WriteF(`<h1>Index of %s</h1>`, req.URL.Path)
	w.WriteF(`<hr />`)
	w.WriteF(`<table>`)
	for _, file := range files {
		name := file.Name()
		if file.IsDir() {
			name += "/"
		}
		w.WriteF(`<tr><td><a href="%s%s">%s</a></td>`, req.URL.Path, name, name)
		w.WriteF(`<td style="width:300px;text-align:center;">%s</td>`, file.ModTime().Format("2006-01-02 15:04:05"))
		w.WriteF(`<td style="width:80px;text-align:right;">%s</td></tr>`, f.formatSize(file))
	}
	w.WriteF(`</table>`)
	w.WriteF(`</body>`)
	w.WriteF(`</html>`)
}

func getLocalIPv4() (string, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, it := range interfaces {
		if it.Name == "WLAN" {
			addrs, err := it.Addrs()
			if err != nil {
				return "", err
			}
			for _, addr := range addrs {
				if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
					if ipnet.IP.To4() != nil {
						return ipnet.IP.String(), nil
					}
				}
			}
		}
	}
	return "", fmt.Errorf("未找到IPv4地址")
}

func dealArgs() {
	if len(os.Args) >= 2 {
		dir = os.Args[1]
		if len(os.Args) >= 3 {
			port = os.Args[2]
		}
	}
}

func main() {
	if len(os.Args) == 2 && os.Args[1] == "/?" {
		fmt.Println("第一个参数改路径,第二个参数改端口")
		return
	}
	dealArgs()
	http.Handle("/backgroundImg", &ImgHandler{})  // 设置背景图片
	http.Handle("/favicon32.ico", &IconHandler{}) // 设置图标
	http.Handle("/", NewFileHandler())
	ip, err := getLocalIPv4() // // 获取局域网IPV4地址
	if err != nil {
		fmt.Println(err)
		ip = "127.0.0.1"
	}
	if port == "80" {
		fmt.Printf("服务已启动,访问地址:http://%s\n", ip)
	} else {
		fmt.Printf("服务已启动,访问地址:http://%s:%s\n", ip, port)
	}
	err = http.ListenAndServe(":"+port, nil)
	if err != nil {
		panic(err)
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值