压缩包解压缩
package main
import (
"archive/zip"
"bytes"
"compress/flate"
"fmt"
"github.com/gin-gonic/gin"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"hash/crc32"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
)
type ZipCrypto struct {
password []byte
Keys [3]uint32
}
func NewZipCrypto(passphrase []byte) *ZipCrypto {
z := &ZipCrypto{}
z.password = passphrase
z.init()
return z
}
func (z *ZipCrypto) init() {
z.Keys[0] = 0x12345678
z.Keys[1] = 0x23456789
z.Keys[2] = 0x34567890
for i := 0; i < len(z.password); i++ {
z.updateKeys(z.password[i])
}
}
func (z *ZipCrypto) updateKeys(byteValue byte) {
z.Keys[0] = crc32update(z.Keys[0], byteValue)
z.Keys[1] += z.Keys[0] & 0xff
z.Keys[1] = z.Keys[1]*134775813 + 1
z.Keys[2] = crc32update(z.Keys[2], (byte)(z.Keys[1]>>24))
}
func (z *ZipCrypto) magicByte() byte {
var t uint32 = z.Keys[2] | 2
return byte((t * (t ^ 1)) >> 8)
}
func (z *ZipCrypto) Encrypt(data []byte) []byte {
length := len(data)
chiper := make([]byte, length)
for i := 0; i < length; i++ {
v := data[i]
chiper[i] = v ^ z.magicByte()
z.updateKeys(v)
}
return chiper
}
func (z *ZipCrypto) Decrypt(chiper []byte) []byte {
length := len(chiper)
plain := make([]byte, length)
for i, c := range chiper {
v := c ^ z.magicByte()
z.updateKeys(v)
plain[i] = v
}
return plain
}
func crc32update(pCrc32 uint32, bval byte) uint32 {
return crc32.IEEETable[(pCrc32^uint32(bval))&0xff] ^ (pCrc32 >> 8)
}
func ZipCryptoDecryptor(r *io.SectionReader, password []byte) (*io.SectionReader, error) {
z := NewZipCrypto(password)
b := make([]byte, r.Size())
r.Read(b)
m := z.Decrypt(b)
return io.NewSectionReader(bytes.NewReader(m), 12, int64(len(m))), nil
}
type unzip struct {
offset int64
fp *os.File
name string
}
func (uz *unzip) init() (err error) {
uz.fp, err = os.Open(uz.name)
return err
}
func (uz *unzip) close() {
if uz.fp != nil {
uz.fp.Close()
}
}
func (uz *unzip) Size() int64 {
if uz.fp == nil {
if err := uz.init(); err != nil {
return -1
}
}
fi, err := uz.fp.Stat()
if err != nil {
return -1
}
return fi.Size() - uz.offset
}
func (uz *unzip) ReadAt(p []byte, off int64) (int, error) {
if uz.fp == nil {
if err := uz.init(); err != nil {
return 0, err
}
}
return uz.fp.ReadAt(p, off+uz.offset)
}
func isInclude(includes []string, fname string) bool {
if includes == nil {
return true
}
for i := 0; i < len(includes); i++ {
if includes[i] == fname {
return true
}
}
return false
}
//DeCompressZip 解压zip包
func DeCompressZip(zipFile, dest, passwd string, includes []string, offset int64) error {
uz := &unzip{offset: offset, name: zipFile}
defer uz.close()
zr, err := zip.NewReader(uz, uz.Size())
if err != nil {
return err
}
if passwd != "" {
// Register a custom Deflate compressor.
zr.RegisterDecompressor(zip.Deflate, func(r io.Reader) io.ReadCloser {
rs := r.(*io.SectionReader)
r, _ = ZipCryptoDecryptor(rs, []byte(passwd))
return flate.NewReader(r)
})
zr.RegisterDecompressor(zip.Store, func(r io.Reader) io.ReadCloser {
rs := r.(*io.SectionReader)
r, _ = ZipCryptoDecryptor(rs, []byte(passwd))
return ioutil.NopCloser(r)
})
}
for _, f := range zr.File {
var decodeName string
if f.Flags == 1 {
//如果标致位是1 则是默认的本地编码 默认为gbk
i := bytes.NewReader([]byte(f.Name))
decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
content, _ := ioutil.ReadAll(decoder)
decodeName = string(content)
} else {
//如果标志为是 0 << 11也就是 2048 则是utf-8编码
decodeName = f.Name
}
fpath := filepath.Join(dest, decodeName)
if f.FileInfo().IsDir() {
os.MkdirAll(fpath, os.ModePerm)
continue
}
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return err
}
inFile, err := f.Open()
if err != nil {
return err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
inFile.Close()
return err
}
_, err = io.Copy(outFile, inFile)
inFile.Close()
outFile.Close()
if err != nil {
return err
}
}
return nil
}
func DeCompressZipByte(zipFile, passwd string, offset int64) (map[string][]byte, error) {
uz := &unzip{offset: offset, name: zipFile}
defer uz.close()
zr, err := zip.NewReader(uz, uz.Size())
if err != nil {
return nil, err
}
if passwd != "" {
zr.RegisterDecompressor(zip.Deflate, func(r io.Reader) io.ReadCloser {
rs := r.(*io.SectionReader)
r, _ = ZipCryptoDecryptor(rs, []byte(passwd))
return flate.NewReader(r)
})
zr.RegisterDecompressor(zip.Store, func(r io.Reader) io.ReadCloser {
rs := r.(*io.SectionReader)
r, _ = ZipCryptoDecryptor(rs, []byte(passwd))
return ioutil.NopCloser(r)
})
}
var chunkMap = make(map[string][]byte)
for _, f := range zr.File {
var decodeName string
if f.Flags == 1 {
//如果标致位是1 则是默认的本地编码 默认为gbk
i := bytes.NewReader([]byte(f.Name))
decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
content, _ := ioutil.ReadAll(decoder)
decodeName = string(content)
} else {
//如果标志为是 0 << 11也就是 2048 则是utf-8编码
decodeName = f.Name
}
inFile, err := f.Open()
if err != nil {
return nil, err
}
defer inFile.Close()
var chunk []byte
buf := make([]byte, 1024)
for {
//从file读取到buf中
n, err := inFile.Read(buf)
if err != nil && err != io.EOF {
fmt.Println("read buf fail", err)
break
}
//说明读取结束
if n == 0 {
break
}
//读取到最终的缓冲区中
chunk = append(chunk, buf[:n]...)
}
chunkMap[decodeName] = chunk
}
return chunkMap, nil
}
func main() {
//err := DeCompressZip("1.zip", "./tmp", "123456", nil, 0) // 解压缩带密码压缩包
//if err != nil {
// fmt.Println(err)
//}
bm, err := DeCompressZipByte("1.zip", "123456", 0) // 读取压缩包文件到byte map
if err != nil {
fmt.Println(err)
return
}
r := gin.Default()
r.GET("/:name", func(c *gin.Context) {
name := c.Param("name")
val, ok := bm[name]
if !ok {
c.String(http.StatusBadGateway, "")
return
}
c.String(200, string(val))
})
r.Run(":8080")
}
最后更新于