gin 使用 pack2 打包 html到二进制

直接上我的一个web播放器的样例代码片段

主要是 LoadTemplate 方法

然后打包的时候需要用packr2工具:

#安装编译工具,用于打包html到二进制
go get -u github.com/gobuffalo/packr/v2/packr2
#build和go build一样,交叉编译的方式也是一样的
CGO_ENABLED=0 GOOS=linux GOARCH=arm packr2 build  -o 115_player
#简单点的
packr2 build  -o 115_player

 

代码片段:

package web

import (
  "crypto/md5"
  "encoding/hex"
  "fmt"
  "github.com/gin-gonic/gin"
  "github.com/gobuffalo/packr/v2"
  "github.com/google/uuid"
  log "github.com/sirupsen/logrus"
  "html/template"
  "net"
  "net/http"
  "os"
  "runtime"
  "strings"
  "time"
)

var MainConsole = make(chan os.Signal, 1)

type webServer struct {
  Engine *gin.Engine
}

type Conf struct {
  User     string
  Password string
}

var Webserver = &webServer{}

type MSG map[string]interface{}

func OK(data interface{}) MSG {
  return MSG{"data": data, "code": 0, "msg": "ok"}
}

func Failed(code int, msg string) MSG {
  return MSG{"data": nil, "code": code, "msg": msg}
}

func (s *webServer) Run(addr string) {
  gin.SetMode(gin.ReleaseMode)
  s.Engine = gin.New()
  // 自动加载模板
  t := template.New("tmp")
  //func 函数映射 全局模板可用
  t.Funcs(template.FuncMap{
    "getYear":        GetYear,
    "formatAsDate":   FormatAsDate,
    "getConf":        GetConf,
    "getDate":        GetDate,
    "getavator":      Getavator,
    "getServerInfo":  GetServerInfo,
    "formatFileSize": FormatFileSize,
  })
  //从二进制中加载模板(后缀必须.html)
  t, _ = s.LoadTemplate(t)
  s.Engine.SetHTMLTemplate(t)
  //静态资源
  assets := packr.New("assets", "../template/assets")
  //s.Engine.Static("/assets", "./template/assets")
  s.Engine.StaticFS("/assets", assets)
  s.Engine.GET("/", func(c *gin.Context) {
    c.Redirect(302, "/index/login")
  })
  //通用路由
  s.Engine.Any("/m3u8/*action", s.AdminM3u8) // 用于代理m3u8的文件和ts文件的全局访问
  s.Engine.Any("/admin/:action", AuthMiddleWare(), s.admin)
  s.Engine.Any("/index/:action", s.index)

  go func() {
    log.Infof("115 player webui 服务器已启动: %v", addr)
    err := s.Engine.Run(addr)
    if err != nil {
      log.Error(err)
      log.Infof("请检查端口是否被占用.")
      time.Sleep(time.Second * 5)
      os.Exit(1)
    }
  }()
  return
}

// loadTemplate loads templates by packr 将html 打包到二进制包
func (s *webServer) LoadTemplate(t *template.Template) (*template.Template, error) {
  box := packr.New("tmp", "../template/html")
  for _, file := range box.List() {
    if !strings.HasSuffix(file, ".html") {
      continue
    }
    h, err := box.FindString(file)
    if err != nil {
      return nil, err
    }
    //拼接方式,组装模板  admin/index.html 这种,方便调用
    t, err = t.New(strings.Replace(file, "html/", "", 1)).Parse(h)
    if err != nil {
      return nil, err
    }
  }
  return t, nil
}

//格式化年月日
func FormatAsDate(t time.Time) string {
  year, month, day := t.Date()
  return fmt.Sprintf("%d%02d/%02d", year, month, day)
}

// 获取年份
func GetYear() string {
  t := time.Now()
  year, _, _ := t.Date()
  return fmt.Sprintf("%d", year)
}

// 获取当前年月日
func GetDate() string {
  t := time.Now()
  year, month, day := t.Date()
  return fmt.Sprintf("%d-%02d-%02d", year, month, day)
}

// 随机获取一个头像
func Getavator() string {
  Uuid := uuid.New().String()
  grav_url := "https://www.gravatar.com/avatar/" + Uuid
  return grav_url
}

type info struct {
  Root       string
  Version    string
  Hostname   string
  Interfaces interface{}
  Goarch     string
  Goos       string
  //VirtualMemory *mem.VirtualMemoryStat
  Sys         uint64
  CpuInfoStat struct {
    Count   int
    Percent []float64
  }
}

func GetServerInfo() *info {
  root := runtime.GOROOT()          // GO 路径
  version := runtime.Version()      //GO 版本信息
  hostname, _ := os.Hostname()      //获得PC名
  interfaces, _ := net.Interfaces() //获得网卡信息
  goarch := runtime.GOARCH          //系统构架 386、amd64
  goos := runtime.GOOS              //系统版本 windows
  Info := &info{
    Root:       root,
    Version:    version,
    Hostname:   hostname,
    Interfaces: interfaces,
    Goarch:     goarch,
    Goos:       goos,
  }

  //v, _ := mem.VirtualMemory()
  //Info.VirtualMemory = v
  var ms runtime.MemStats
  runtime.ReadMemStats(&ms)
  Info.Sys = ms.Sys
  //Info.CpuInfoStat.Count, _ = cpu.Counts(true)
  //Info.CpuInfoStat.Percent, _ = cpu.Percent(0, true)
  return Info
}

// 字节的单位转换 保留两位小数
func FormatFileSize(fileSize uint64) (size string) {
  if fileSize < 1024 {
    //return strconv.FormatInt(fileSize, 10) + "B"
    return fmt.Sprintf("%.2fB", float64(fileSize)/float64(1))
  } else if fileSize < (1024 * 1024) {
    return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(1024))
  } else if fileSize < (1024 * 1024 * 1024) {
    return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(1024*1024))
  } else if fileSize < (1024 * 1024 * 1024 * 1024) {
    return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(1024*1024*1024))
  } else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
    return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(1024*1024*1024*1024))
  } else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
    return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
  }
}

// admin 控制器 登录验证
func AuthMiddleWare() gin.HandlerFunc {
  return func(c *gin.Context) {
    //conf := GetConf()
    user := "admin"
    password := "admin"
    str1 := user + password
    h := md5.New()
    h.Write([]byte(str1))
    md51 := hex.EncodeToString(h.Sum(nil))
    if cookie, err := c.Request.Cookie("userinfo"); err == nil {
      value := cookie.Value
      if value == md51 {
        c.Next()
        return
      }
    }
    c.HTML(http.StatusOK, "index/jump.html", gin.H{
      "url":     "/index/login",
      "timeout": "3",
      "code":    0, //1为success,0为error
      "msg":     "请登录后再访问",
    })
    //c.Redirect(http.StatusMovedPermanently, "/index/login")
    c.Abort()
    return
  }
}

func (s *webServer) admin(c *gin.Context) {
  action := c.Param("action")
  log.Debugf("webServer接收到cgi调用: %v", action)
  if f, ok := HttpuriAdmin[action]; ok {
    f(s, c)
  } else {
    c.JSON(200, Failed(404, "没有相关页面"))
  }
}

func (s *webServer) index(c *gin.Context) {
  action := c.Param("action")
  log.Debugf("webServer接收到cgi调用: %v", action)
  if f, ok := HttpuriIndex[action]; ok {
    f(s, c)
  } else {
    c.JSON(200, Failed(404, "没有相关页面"))
  }
}

// 获取当前配置文件信息
func GetConf() Conf {
  conf := Conf{User: "admin", Password: "admin"}
  return conf
}

func Error(c *gin.Context, msg string, timeout int, url string) {
  c.HTML(http.StatusOK, "index/jump.html", gin.H{
    "url":     url,
    "timeout": timeout,
    "code":    0, //1为success,0为error
    "msg":     msg,
  })
  c.Abort()
  return
}

 

打赏
Bookmark the permalink.
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论