1 Star 0 Fork 0

h79/goutils

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
api
auth
build
common
algorithm
app
archive
gzip
tar
targz
tarxz
testdata
zip
zip.go
zip_test.go
archive.go
zip.go
attributes
banner
bus
coder
compress
config
data
debug
file
git
http
images
json
list
logger
mapper
option
perf
queue
random
result
scheduler
secret
server
ssh
stringutil
svc
system
tag
template
timer
trie
version
watcher
xml
yaml
bit_flag.go
common.go
integer.go
dao
discovery
loader
mq
plugins
request
rpc
sensitive
thrift
.gitignore
LICENSE
Makefile
README.md
doc.go
error.md
go.mod
go.sum
goutils.go
goutils_test.go
version.go
克隆/下载
zip.go 3.02 KB
一键复制 编辑 原始数据 按行查看 历史
huqiuyun 提交于 1年前 . build
// Package zip implements the Archive interface providing zip archiving
// and compression.
package zip
import (
"archive/zip"
"compress/flate"
"fmt"
fileconfig "gitee.com/h79/goutils/common/file/config"
"io"
"io/fs"
"os"
"path/filepath"
)
// Archive zip struct.
type Archive struct {
z *zip.Writer
files map[string]bool
}
// New zip archive.
func New(target io.Writer) Archive {
compressor := zip.NewWriter(target)
compressor.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
return flate.NewWriter(out, flate.BestCompression)
})
return Archive{
z: compressor,
files: map[string]bool{},
}
}
// New zip archive.
func Copying(source *os.File, target io.Writer) (Archive, error) {
info, err := source.Stat()
if err != nil {
return Archive{}, err
}
r, err := zip.NewReader(source, info.Size())
if err != nil {
return Archive{}, err
}
w := New(target)
for _, zf := range r.File {
w.files[zf.Name] = true
hdr := zip.FileHeader{
Name: zf.Name,
UncompressedSize64: zf.UncompressedSize64,
UncompressedSize: zf.UncompressedSize,
CreatorVersion: zf.CreatorVersion,
ExternalAttrs: zf.ExternalAttrs,
}
ww, err := w.z.CreateHeader(&hdr)
if err != nil {
return Archive{}, fmt.Errorf("creating %q header in target: %w", zf.Name, err)
}
if zf.Mode().IsDir() {
continue
}
rr, err := zf.Open()
if err != nil {
return Archive{}, fmt.Errorf("opening %q from source: %w", zf.Name, err)
}
defer rr.Close()
if _, err = io.Copy(ww, rr); err != nil {
return Archive{}, fmt.Errorf("copy from %q source to target: %w", zf.Name, err)
}
_ = rr.Close()
}
return w, nil
}
// Close all closeables.
func (a Archive) Close() error {
return a.z.Close()
}
// Add a file to the zip archive.
func (a Archive) Add(f fileconfig.File, stream ...fileconfig.ReaderStream) error {
if f.Destination == "" {
_, f.Destination = filepath.Split(f.Source)
}
if _, ok := a.files[f.Destination]; ok {
return &fs.PathError{Err: fs.ErrExist, Path: f.Destination, Op: "add"}
}
a.files[f.Destination] = true
info, err := os.Lstat(f.Source) // #nosec
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = f.Destination
if info.IsDir() {
header.Name += `/`
} else {
header.Method = zip.Deflate
}
if !f.Info.ParsedMTime.IsZero() {
header.Modified = f.Info.ParsedMTime
}
if f.Info.Mode != 0 {
header.SetMode(f.Info.Mode)
}
w, err := a.z.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if info.Mode()&os.ModeSymlink != 0 {
link, err := os.Readlink(f.Source) // #nosec
if err != nil {
return fmt.Errorf("%s: %w", f.Source, err)
}
_, err = io.WriteString(w, filepath.ToSlash(link))
return err
}
file, err := os.Open(f.Source) // #nosec
if err != nil {
return err
}
defer file.Close()
if _, err = io.Copy(w, file); err != nil {
return err
}
for i := range stream {
stream[i].OnReader(file)
}
return nil
}
// TODO: test fileinfo stuff
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/h79/goutils.git
git@gitee.com:h79/goutils.git
h79
goutils
goutils
v1.8.87

搜索帮助