静态资源打包rice

静态资源打包rice

go在打包的时候,源代码能打包,其他用的的资源文件,如果不特殊处理,是不会打包的文件里面的。所以,有这样的一种需求,打包生成的文件,最好只有一个exe执行文件,这样,方便使用。用过filebrowser工具,构建好的文件,只是一个文件,看过它的源码,需要安装rice工具。所以呢,本文,简单的记录rice的使用。

参考资源

使用步骤

安装工具

理论上下面第2个命令执行就能安装工具,但是,我也执行了前一个命令。

go get github.com/GeertJohan/go.rice
go get github.com/GeertJohan/go.rice/...

代码

改造好后的代码,如下,一是引入库,二是添加下面这句。

rice.MustFindBox("public").HTTPBox()))

改造后:

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"

	"github.com/GeertJohan/go.rice"
)

var port = flag.String("port", "8082", "web监听的端口")
var rootdir = flag.String("root", ".", "web服务器的根目录")

func main() {
	flag.Parse()

	handleString("/", index)
	handleString("/frame.js", framejs)

	http.HandleFunc("/getdir/", getdir)
	http.HandleFunc("/search/", search)
	http.HandleFunc("/download/", downloadFile)
	//http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("public/"))))
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(rice.MustFindBox("public").HTTPBox())))
	fmt.Println("web服务监听的端口: " + *port)
	fmt.Println("请浏览器输入以下地址访问")
	fmt.Println("http://localhost:" + *port)

	log.Fatal(http.ListenAndServe(":"+*port, nil))
}

func handleString(pattern, content string) {
	http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, content)
	})
}

type dirinfo struct {
	Id      string `json:"id"`
	Text    string `json:"text"`
	AbsPath string `json:"absPath"`
	Leaf    bool   `json:"leaf"`
}
type dirinfolist []*dirinfo

//获取目录
func getdir(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	var dlist dirinfolist
	path := r.PostForm.Get("node")
	if path == "src" || path == "" {
		path = *rootdir
	}
	// fmt.Println("path:", path)
	fileInfoList, err := ioutil.ReadDir(path)
	if err != nil {
		log.Fatal(err)
	}
	// fmt.Println(len(fileInfoList))
	for i := range fileInfoList {
		if !fileInfoList[i].IsDir() {
			continue
		}
		curdir := fileInfoList[i].Name()
		absPath := path + "/" + curdir
		// fmt.Println(curdir) //打印当前文件或目录下的文件或目录名
		dinfo := &dirinfo{absPath, curdir, absPath, false}
		dlist = append(dlist, dinfo)
	}
	jsonbyte, _ := json.Marshal(dlist)
	// fmt.Print(string(jsonstr))
	fmt.Fprint(w, string(jsonbyte))
}

type fileinfo struct {
	Abspath string `json:"abspath"`
	Path    string `json:"path"`
	Name    string `json:"name"`
	Mtime   string `json:"mtime"`
	Size    int64  `json:"size"`
}

type fnlist []*fileinfo

//查找对应的文件
func search(w http.ResponseWriter, r *http.Request) {
	var result fnlist
	r.ParseForm()
	path := r.PostForm.Get("path")
	// date := r.PostForm.Get("date")
	// fmt.Println(date)
	// fmt.Println(path)
	if len(path) == 0 {
		path = *rootdir
	}

	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		count := 0
		if !info.IsDir() {
			count += 1
			result = append(result, &fileinfo{path, path, info.Name(), info.ModTime().String(), info.Size()})
			if count > 5000 {
				return nil
			}
		}

		return nil
	})

	if len(result) > 0 {
		jsonbyte, _ := json.Marshal(result)
		fmt.Fprint(w, string(jsonbyte))
	} else {
		fmt.Fprint(w, "[]")
	}
}

//下载文件
func downloadFile(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	fileFullPath := r.Form.Get("path")

	file, err := os.Open(fileFullPath)
	if err != nil {
		fmt.Fprint(w, "文件不存在。")
		return
	}

	defer file.Close()
	fileName := path.Base(fileFullPath)
	fmt.Println("文件名:", fileName)

	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("content-disposition", "attachment; filename=\""+fileName+"\"")
	_, error := io.Copy(w, file)
	if error != nil {
		fmt.Println("error:", err.Error())
		return
	}
}

在main.go文件下,执行编译资源命令

# rice -h  查看帮助
# 打包资源文件,会生成一个rice-box.go文件。
rice embed-go

总结

在开发期,可以不编译资源,也能使用,这样就方便开发调试,随时更改资源文件。另外,是否运行期,也能生效呢?不得而知。