2a4459b9 by Francois

Create memzipfile.go

1 parent 495033b9
1 package beego
2
3 import (
4 "bytes"
5 "compress/flate"
6 "compress/gzip"
7 "errors"
8 //"fmt"
9 "io"
10 "io/ioutil"
11 "net/http"
12 "os"
13 "strings"
14 "time"
15 )
16
17 var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo)
18
19 //TODO: 加锁保证数据完整性
20 func OpenMemZipFile(path string, zip string) (*MemFile, error) {
21 osfile, e := os.Open(path)
22 if e != nil {
23 return nil, e
24 }
25 defer osfile.Close()
26
27 osfileinfo, e := osfile.Stat()
28 if e != nil {
29 return nil, e
30 }
31
32 modtime := osfileinfo.ModTime()
33 fileSize := osfileinfo.Size()
34
35 cfi, ok := gmfim[zip+":"+path]
36 if ok && cfi.ModTime() == modtime && cfi.fileSize == fileSize {
37 //fmt.Printf("read %s file %s from cache\n", zip, path)
38 } else {
39 //fmt.Printf("NOT read %s file %s from cache\n", zip, path)
40 var content []byte
41 if zip == "gzip" {
42 //将文件内容压缩到zipbuf中
43 var zipbuf bytes.Buffer
44 gzipwriter, e := gzip.NewWriterLevel(&zipbuf, gzip.BestCompression)
45 if e != nil {
46 return nil, e
47 }
48 _, e = io.Copy(gzipwriter, osfile)
49 gzipwriter.Close()
50 if e != nil {
51 return nil, e
52 }
53 //读zipbuf到content
54 content, e = ioutil.ReadAll(&zipbuf)
55 if e != nil {
56 return nil, e
57 }
58 } else if zip == "deflate" {
59 //将文件内容压缩到zipbuf中
60 var zipbuf bytes.Buffer
61 deflatewriter, e := flate.NewWriter(&zipbuf, flate.BestCompression)
62 if e != nil {
63 return nil, e
64 }
65 _, e = io.Copy(deflatewriter, osfile)
66 deflatewriter.Close()
67 if e != nil {
68 return nil, e
69 }
70 //将zipbuf读入到content
71 content, e = ioutil.ReadAll(&zipbuf)
72 if e != nil {
73 return nil, e
74 }
75 } else {
76 content, e = ioutil.ReadAll(osfile)
77 if e != nil {
78 return nil, e
79 }
80 }
81
82 cfi = &MemFileInfo{osfileinfo, modtime, content, int64(len(content)), fileSize}
83 gmfim[zip+":"+path] = cfi
84 //fmt.Printf("%s file %s to %d, cache it\n", zip, path, len(content))
85 }
86 return &MemFile{fi: cfi, offset: 0}, nil
87 }
88
89 type MemFileInfo struct {
90 os.FileInfo
91 modTime time.Time
92 content []byte
93 contentSize int64
94 fileSize int64
95 }
96
97 func (fi *MemFileInfo) Name() string {
98 return fi.Name()
99 }
100
101 func (fi *MemFileInfo) Size() int64 {
102 return fi.contentSize
103 }
104
105 func (fi *MemFileInfo) Mode() os.FileMode {
106 return fi.Mode()
107 }
108
109 func (fi *MemFileInfo) ModTime() time.Time {
110 return fi.modTime
111 }
112
113 func (fi *MemFileInfo) IsDir() bool {
114 return fi.IsDir()
115 }
116
117 func (fi *MemFileInfo) Sys() interface{} {
118 return nil
119 }
120
121 type MemFile struct {
122 fi *MemFileInfo
123 offset int64
124 }
125
126 func (f *MemFile) Close() error {
127 return nil
128 }
129
130 func (f *MemFile) Stat() (os.FileInfo, error) {
131 return f.fi, nil
132 }
133
134 func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) {
135 infos := []os.FileInfo{}
136
137 return infos, nil
138 }
139
140 func (f *MemFile) Read(p []byte) (n int, err error) {
141 if len(f.fi.content)-int(f.offset) >= len(p) {
142 n = len(p)
143 } else {
144 n = len(f.fi.content) - int(f.offset)
145 err = io.EOF
146 }
147 copy(p, f.fi.content[f.offset:f.offset+int64(n)])
148 f.offset += int64(n)
149 return
150 }
151
152 var errWhence = errors.New("Seek: invalid whence")
153 var errOffset = errors.New("Seek: invalid offset")
154
155 func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
156 switch whence {
157 default:
158 return 0, errWhence
159 case os.SEEK_SET:
160 case os.SEEK_CUR:
161 offset += f.offset
162 case os.SEEK_END:
163 offset += int64(len(f.fi.content))
164 }
165 if offset < 0 || int(offset) > len(f.fi.content) {
166 return 0, errOffset
167 }
168 f.offset = offset
169 return f.offset, nil
170 }
171
172 //返回: gzip, deflate, 优先gzip
173 //返回空, 表示不zip
174 func GetAcceptEncodingZip(r *http.Request) string {
175 ss := r.Header.Get("Accept-Encoding")
176 ss = strings.ToLower(ss)
177 if strings.Contains(ss, "gzip") {
178 return "gzip"
179 } else if strings.Contains(ss, "deflate") {
180 return "deflate"
181 } else {
182 return ""
183 }
184 }
185
186 func CloseZWriter(zwriter io.Writer) {
187 if zwriter == nil {
188 return
189 }
190
191 switch zwriter.(type) {
192 case *gzip.Writer:
193 zwriter.(*gzip.Writer).Close()
194 case *flate.Writer:
195 zwriter.(*flate.Writer).Close()
196 //其他情况不close, 保持和默认(非压缩)行为一致
197 /*
198 case io.WriteCloser:
199 zwriter.(io.WriteCloser).Close()
200 */
201 }
202 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!