github.com/gogf/gf@v1.16.9/os/gres/gres_func.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gres 8 9 import ( 10 "archive/zip" 11 "bytes" 12 "encoding/hex" 13 "fmt" 14 15 "github.com/gogf/gf/encoding/gbase64" 16 "github.com/gogf/gf/encoding/gcompress" 17 "github.com/gogf/gf/text/gstr" 18 19 "github.com/gogf/gf/os/gfile" 20 ) 21 22 const ( 23 packedGoSouceTemplate = ` 24 package %s 25 26 import "github.com/gogf/gf/os/gres" 27 28 func init() { 29 if err := gres.Add("%s"); err != nil { 30 panic("add binary content to resource manager failed: " + err.Error()) 31 } 32 } 33 ` 34 ) 35 36 // Pack packs the path specified by <srcPaths> into bytes. 37 // The unnecessary parameter <keyPrefix> indicates the prefix for each file 38 // packed into the result bytes. 39 // 40 // Note that parameter <srcPaths> supports multiple paths join with ','. 41 func Pack(srcPaths string, keyPrefix ...string) ([]byte, error) { 42 var ( 43 buffer = bytes.NewBuffer(nil) 44 headerPrefix = "" 45 ) 46 if len(keyPrefix) > 0 && keyPrefix[0] != "" { 47 headerPrefix = keyPrefix[0] 48 } 49 err := zipPathWriter(srcPaths, buffer, headerPrefix) 50 if err != nil { 51 return nil, err 52 } 53 // Gzip the data bytes to reduce the size. 54 return gcompress.Gzip(buffer.Bytes(), 9) 55 } 56 57 // PackToFile packs the path specified by <srcPaths> to target file <dstPath>. 58 // The unnecessary parameter <keyPrefix> indicates the prefix for each file 59 // packed into the result bytes. 60 // 61 // Note that parameter <srcPaths> supports multiple paths join with ','. 62 func PackToFile(srcPaths, dstPath string, keyPrefix ...string) error { 63 data, err := Pack(srcPaths, keyPrefix...) 64 if err != nil { 65 return err 66 } 67 return gfile.PutBytes(dstPath, data) 68 } 69 70 // PackToGoFile packs the path specified by <srcPaths> to target go file <goFilePath> 71 // with given package name <pkgName>. 72 // 73 // The unnecessary parameter <keyPrefix> indicates the prefix for each file 74 // packed into the result bytes. 75 // 76 // Note that parameter <srcPaths> supports multiple paths join with ','. 77 func PackToGoFile(srcPath, goFilePath, pkgName string, keyPrefix ...string) error { 78 data, err := Pack(srcPath, keyPrefix...) 79 if err != nil { 80 return err 81 } 82 return gfile.PutContents( 83 goFilePath, 84 fmt.Sprintf(gstr.TrimLeft(packedGoSouceTemplate), pkgName, gbase64.EncodeToString(data)), 85 ) 86 } 87 88 // Unpack unpacks the content specified by <path> to []*File. 89 func Unpack(path string) ([]*File, error) { 90 realPath, err := gfile.Search(path) 91 if err != nil { 92 return nil, err 93 } 94 return UnpackContent(gfile.GetContents(realPath)) 95 } 96 97 // UnpackContent unpacks the content to []*File. 98 func UnpackContent(content string) ([]*File, error) { 99 var data []byte 100 var err error 101 if isHexStr(content) { 102 // It here keeps compatible with old version packing string using hex string. 103 // TODO remove this support in the future. 104 data, err = gcompress.UnGzip(hexStrToBytes(content)) 105 if err != nil { 106 return nil, err 107 } 108 } else if isBase64(content) { 109 // New version packing string using base64. 110 b, err := gbase64.DecodeString(content) 111 if err != nil { 112 return nil, err 113 } 114 data, err = gcompress.UnGzip(b) 115 if err != nil { 116 return nil, err 117 } 118 } else { 119 data, err = gcompress.UnGzip([]byte(content)) 120 if err != nil { 121 return nil, err 122 } 123 } 124 reader, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) 125 if err != nil { 126 return nil, err 127 } 128 array := make([]*File, len(reader.File)) 129 for i, file := range reader.File { 130 array[i] = &File{file: file} 131 } 132 return array, nil 133 } 134 135 // isBase64 checks and returns whether given content <s> is base64 string. 136 // It returns true if <s> is base64 string, or false if not. 137 func isBase64(s string) bool { 138 var r bool 139 for i := 0; i < len(s); i++ { 140 r = (s[i] >= '0' && s[i] <= '9') || 141 (s[i] >= 'a' && s[i] <= 'z') || 142 (s[i] >= 'A' && s[i] <= 'Z') || 143 (s[i] == '+' || s[i] == '-') || 144 (s[i] == '_' || s[i] == '/') || s[i] == '=' 145 if !r { 146 return false 147 } 148 } 149 return true 150 } 151 152 // isHexStr checks and returns whether given content <s> is hex string. 153 // It returns true if <s> is hex string, or false if not. 154 func isHexStr(s string) bool { 155 var r bool 156 for i := 0; i < len(s); i++ { 157 r = (s[i] >= '0' && s[i] <= '9') || 158 (s[i] >= 'a' && s[i] <= 'f') || 159 (s[i] >= 'A' && s[i] <= 'F') 160 if !r { 161 return false 162 } 163 } 164 return true 165 } 166 167 // hexStrToBytes converts hex string content to []byte. 168 func hexStrToBytes(s string) []byte { 169 src := []byte(s) 170 dst := make([]byte, hex.DecodedLen(len(src))) 171 hex.Decode(dst, src) 172 return dst 173 }