gres资源管理

GF框架从v1.9版本开始提供了资源管理的特性,由gres模块实现,该模块具有以下特点:

  • 可将任意的文件打包为Go内容,支持开发者自定义加解密;
  • 资源管理器内容完全基于内存,并且内容只读,无法动态修改;
  • 资源管理器默认整合支持到了WebServer、配置管理、模板引擎中;
  • 任意文件如网站静态文件、配置文件等可编译到二进制文件中,也可编译到发布的可执行文件中;
  • 开发者可只需编译发布一个可执行文件,除了方便了软件分发,也为保护软件知识产权内容提供了可能;

使用方式

  1. import "github.com/gogf/gf/os/gres"

接口文档

https://godoc.org/github.com/gogf/gf/os/gres

  1. func Add(content []byte, prefix ...string) error
  2. func Contains(path string) bool
  3. func Dump()
  4. func GetContent(path string) []byte
  5. func IsEmpty() bool
  6. func Get(path string) *File
  7. func GetWithIndex(path string, indexFiles []string) *File
  8. func ScanDir(path string, pattern string, recursive ...bool) []*File
  9. func ScanDirFile(path string, pattern string, recursive ...bool) []*File
  10. func Load(path string, prefix ...string) error
  11. func Pack(srcPaths string, keyPrefix ...string) ([]byte, error)
  12. func PackToGoFile(srcPath, goFilePath, pkgName string, keyPrefix ...string) error
  13. func PackToFile(srcPaths, dstPath string, keyPrefix ...string) error
  14. func Unpack(path string) ([]*File, error)
  15. func UnpackContent(content []byte) ([]*File, error)
  16. type File
  17. func (f *File) Close() error
  18. func (f *File) Content() []byte
  19. func (f *File) FileInfo() os.FileInfo
  20. func (f *File) Name() string
  21. func (f *File) Open() (io.ReadCloser, error)
  22. func (f *File) Read(b []byte) (n int, err error)
  23. func (f *File) Readdir(count int) ([]os.FileInfo, error)
  24. func (f *File) Seek(offset int64, whence int) (int64, error)
  25. func (f *File) Stat() (os.FileInfo, error)
  26. type Resource
  27. func Instance(name ...string) *Resource
  28. func New() *Resource
  29. func (r *Resource) Add(content []byte, prefix ...string) error
  30. func (r *Resource) Contains(path string) bool
  31. func (r *Resource) Dump()
  32. func (r *Resource) Get(path string) *File
  33. func (r *Resource) GetContent(path string) []byte
  34. func (r *Resource) GetWithIndex(path string, indexFiles []string) *File
  35. func (r *Resource) IsEmpty() bool
  36. func (r *Resource) Load(path string, prefix ...string) error
  37. func (r *Resource) ScanDir(path string, pattern string, recursive ...bool) []*File
  38. func (r *Resource) ScanDirFile(path string, pattern string, recursive ...bool) []*File
  1. 通过Pack*/Unpack*方法可以实现对任意文件的打包/解包功能,可以打包到二进制文件或者Go代码文件;
  2. 资源管理由Resource对象实现,可实现对打包内容的添加,文件的检索查找,以及对目录的遍历等功能;
  3. 资源文件由File对象实现,该文件对象和os.File文件对象类似,并且该对象实现了http.File接口;
  4. ScanDir用于针对于特定目录下的文件/目录检索,并且支持递归检索;
  5. ScanDirFile用于针对于特定目录下的文件检索,并且支持递归检索;
  6. 通过Dump方法在终端打印出Resource资源对象所有的文件列表,资源管理器中的文件分隔符号统一为/
  7. 此外,gres资源管理模块提供了默认的Resource对象,并通过包方法提供了对该默认对象的操作;

文件/目录打包

开发者对文件/目录的打包可以自定义通过Pack*方法实现,并通过Unpack*方法自行对二进制文件进行打包;或者通过import方式导入打包的Go资源文件。

开发者也可以通过gf命令行工具的pack命令实现对任意文件的打包,具体请查看CLI工具链章节。通过命令行工具的pack命令也是比较推荐的打包方式。

可以通过Pack方法直接生成打包后的[]byte内容,开发者可以对该内容进行自定义加密以额外增加文件内容的安全性。随后可以在程序中对该[]byte解密后,并通过UnpackContent方法可以对该内容进行解包,使用该打包内容。

打包生成Go文件

这种是比较常用的方式,我们这里直接使用gf工具来进行打包,不添加自定义的加密。

1. gf pack生成Go文件

比较推荐的方式是将Go文件直接生成到boot启动目录,并设置生成Go文件的包名为boot,这样该资源文件将会被自动引入到项目中。我们将项目的config,public,template三个目录的文件打包到Go文件,打包命令为:gf pack config,public,template boot/data.go -n boot

生成的Go文件内容类似于:

  1. import "github.com/gogf/gf/os/gres"
  2. func init() {
  3. if err := gres.Add([]byte("\x50\x4b\x03\x04\x14\x00\x08...")); err != nil {
  4. panic(err)
  5. }
  6. }

2. 使用打包的Go资源文件

由于项目的main入口程序文件会引入boot包,例如像这样(module名称为my-app):

  1. import (
  2. _ "my-app/boot"
  3. )

随后可以在项目的任何地方使用gres模块来访问打包的资源文件。

如果使用GF推荐的项目目录结构,在目录结构中会存在boot目录(对应包名也是boot),用于程序启动设置。因此如果将Go资源文件打包到boot目录下,那么将会被自动编译进可执行文件中。

3. 打印资源管理文件列表

可以通过Dump()方法打印出当前资源管理器中所有的文件列表,输出内容类似于:

  1. 2019-09-15T13:36:28+00:00 0.00B config
  2. 2019-07-27T07:26:12+00:00 1.34K config/config.toml
  3. 2019-09-15T13:36:28+00:00 0.00B public
  4. 2019-06-25T17:03:56+00:00 0.00B public/resource
  5. 2018-12-04T12:50:16+00:00 0.00B public/resource/css
  6. 2018-12-17T12:54:26+00:00 0.00B public/resource/css/document
  7. 2018-12-17T12:54:26+00:00 4.20K public/resource/css/document/style.css
  8. 2018-08-24T01:46:58+00:00 32.00B public/resource/css/index.css
  9. 2019-05-23T03:51:24+00:00 0.00B public/resource/image
  10. 2018-08-20T05:02:08+00:00 24.01K public/resource/image/cover.png
  11. 2019-05-23T03:51:24+00:00 4.19K public/resource/image/favicon.ico
  12. 2018-08-23T01:44:50+00:00 4.19K public/resource/image/gf.ico
  13. 2018-12-04T13:04:34+00:00 0.00B public/resource/js
  14. 2019-06-27T11:06:12+00:00 0.00B public/resource/js/document
  15. 2019-06-27T11:06:12+00:00 11.67K public/resource/js/document/index.js
  16. 2019-09-15T13:36:28+00:00 0.00B template
  17. 2019-02-02T09:08:56+00:00 0.00B template/document
  18. 2018-12-04T12:49:08+00:00 0.00B template/document/include
  19. 2018-12-04T12:49:08+00:00 329.00B template/document/include/404.html
  20. 2019-03-06T01:52:56+00:00 3.42K template/document/index.html
  21. ...

自定义打包/解包

自定义打包示例

我们将项目根目录下的publicconfig目录打包为data.bin二进制文件,并通过gaes加密算法对生成的二进制内容进行加密。

  1. package main
  2. import (
  3. "github.com/gogf/gf/crypto/gaes"
  4. "github.com/gogf/gf/os/gfile"
  5. "github.com/gogf/gf/os/gres"
  6. )
  7. var (
  8. CryptoKey = []byte("x76cgqt36i9c863bzmotuf8626dxiwu0")
  9. )
  10. func main() {
  11. binContent, err := gres.Pack("public,config")
  12. if err != nil {
  13. panic(err)
  14. }
  15. binContent, err = gaes.Encrypt(binContent, CryptoKey)
  16. if err != nil {
  17. panic(err)
  18. }
  19. if err := gfile.PutBytes("data.bin", binContent); err != nil {
  20. panic(err)
  21. }
  22. }

自定义解包示例

我们使用将刚才打包生成的data.bin,需要解密和解包两步操作。

  1. package main
  2. import (
  3. "github.com/gogf/gf/crypto/gaes"
  4. "github.com/gogf/gf/os/gfile"
  5. "github.com/gogf/gf/os/gres"
  6. )
  7. var (
  8. CryptoKey = []byte("x76cgqt36i9c863bzmotuf8626dxiwu0")
  9. )
  10. func main() {
  11. binContent := gfile.GetBytes("data.bin")
  12. binContent, err := gaes.Decrypt(binContent, CryptoKey)
  13. if err != nil {
  14. panic(err)
  15. }
  16. if err := gres.Add(binContent); err != nil {
  17. panic(err)
  18. }
  19. gres.Dump()
  20. }

最后,我们使用gres.Dump()打印出添加成功的文件列表。