代码拉取完成,页面将自动刷新
同步操作将从 kitfast/资源管理库 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
package resml
import (
"bytes"
"embed"
"fmt"
"html/template"
"io"
"io/fs"
"net/http"
"path/filepath"
"strings"
"sync"
"time"
)
// 嵌入 webui 文件系统。
// 使用方法:
//
// http.Handle("/prefix/", http.StripPrefix("/prefix/", http.FileServerFS(webui)))
//
// 注:go:embed 与它前面的 // 之间不能有空格,否则不会嵌入文件。
//
//go:embed all:webui
var webui embed.FS
// WebUI 组合 fs.FS 与 http.Handler 接口。
// http.FileSystem 接口与 fs.FS 兼容,可以直接转为 http.FileSystem。
type WebUi interface {
fs.FS
http.Handler
}
// Web UI 的变量
type WebUiVars struct {
Title string // 标题
}
// WebUI 文件系统。
type webUiHandler struct {
mu sync.Mutex
prefix string
index *TemplateFile
vars *WebUiVars
}
// 实现 http.FileSystem 接口。
func (fs *webUiHandler) Open(name string) (fs.File, error) {
fs.mu.Lock()
defer fs.mu.Unlock()
// 此处的 /webui 是嵌入文件系统的前缀,是固定值,而不是请求 path 的前缀
name = strings.TrimPrefix(name, "/webui/")
if !strings.HasPrefix(name, "webui/") {
name = fmt.Sprintf("webui/%s", strings.TrimLeft(name, "/"))
}
if strings.HasSuffix(name, "/.") {
name = name[:len(name)-1] + "index.html"
}
fd, err := webui.Open(name)
if err != nil {
return nil, err
}
if stat, err := fd.Stat(); err == nil && stat.IsDir() {
if fs.index != nil {
return fs.index.newReader(), nil
}
name = fmt.Sprintf("%s/index.html", strings.TrimRight(name, "/"))
fd, err = webui.Open(name)
if err != nil {
return nil, err
}
}
if strings.HasSuffix(name, "/index.html") {
if fs.index != nil {
return fs.index.newReader(), nil
}
fs.index, err = NewTemplateFile(fd, name, fs.vars)
if err != nil {
return nil, err
}
return fs.index.newReader(), nil
}
return fd, nil
}
// 实现 http.Handler 接口。
func (fs *webUiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if fs.prefix == "" {
http.ServeFileFS(w, r, fs, r.URL.Path)
return
}
name := strings.Trim(strings.TrimPrefix(r.URL.Path, fs.prefix), "/") // 去掉前缀与 / 字符
if name == "" || name == "." {
name = "index.html"
}
http.ServeFileFS(w, r, fs, name)
}
// 创建 WebUi 实例。
func NewWebUi(prefix string) WebUi {
return NewWebUiVars(prefix, nil)
}
// 创建 WebUi 实例。
func NewWebUiVars(prefix string, vars *WebUiVars) WebUi {
h := &webUiHandler{prefix: strings.TrimSpace(prefix), vars: vars}
if h.vars == nil {
h.vars = &WebUiVars{Title: "文件管理系统"}
} else if strings.TrimSpace(h.vars.Title) == "" {
h.vars.Title = "文件管理系统"
}
return h
}
// 获取 WebUI 的嵌入文件系统。它的文件路径为 webui/*,例如 webui/index.html。
func WebUiEmbedFs() embed.FS {
return webui
}
type TemplateFile struct {
rd *bytes.Reader
ln int64
buf []byte
name string
mt time.Time
}
func (f *TemplateFile) newReader() *TemplateFile {
return &TemplateFile{rd: bytes.NewReader(f.buf), ln: int64(len(f.buf)), name: f.name, mt: f.mt}
}
func (f *TemplateFile) Close() error {
return nil
}
func (f *TemplateFile) Read(p []byte) (n int, err error) {
if f.rd != nil {
return f.rd.Read(p)
}
return 0, io.ErrNoProgress
}
func (f *TemplateFile) Stat() (fs.FileInfo, error) {
return f, nil
}
func (f *TemplateFile) Name() string {
return f.name
}
func (f *TemplateFile) Size() int64 {
return f.ln
}
func (f *TemplateFile) Mode() fs.FileMode {
return 0644
}
func (f *TemplateFile) ModTime() time.Time {
return f.mt
}
func (f *TemplateFile) IsDir() bool {
return false
}
func (f *TemplateFile) Sys() any {
return nil
}
func NewTemplateFile(fd fs.File, name string, vars any) (*TemplateFile, error) {
body, err := io.ReadAll(fd)
fd.Close()
if err != nil {
return nil, err
}
t, err := template.New(name).Parse(string(body))
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
if err = t.Execute(buf, vars); err != nil {
return nil, err
}
return &TemplateFile{buf: buf.Bytes(), name: filepath.Base(name), mt: time.Now()}, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。