pkg/files/file_util.go

154 lines
2.5 KiB
Go
Raw Permalink Normal View History

2023-09-18 15:58:52 +08:00
package files
2023-09-18 15:51:20 +08:00
import (
"errors"
"io"
2023-09-18 15:58:52 +08:00
"lab.evlic.cn/go/pkg/md5"
2023-09-18 15:51:20 +08:00
"mime/multipart"
2023-09-18 15:58:52 +08:00
"os"
2023-09-18 15:51:20 +08:00
"path/filepath"
"strings"
"go.uber.org/zap"
)
func FileSave(r io.Reader, dst string) (err error) {
var (
fp string
out io.WriteCloser
)
fp = filepath.Dir(dst)
err = DirCheck(fp)
out, err = os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, r)
return
}
// FileMD5 计算文件 md5 值
func FileMD5(file string) (string, error) {
f, err := os.Open(file)
if err != nil {
return "", err
}
info, err := f.Stat()
if err != nil {
return "", err
}
size := info.Size()
return md5.Sum(f, size, BlockSize, ChunkSize)
}
func MultipartMD5(fh *multipart.FileHeader) (string, error) {
f, err := fh.Open()
if err != nil {
return "", err
}
size := fh.Size
return md5.Sum(f, size, BlockSize, ChunkSize)
}
const (
BlockSize = 1 << 10
ChunkSize = BlockSize << 2
)
var (
ErrorIsNotDir = errors.New("path is not dir. ")
)
func DirCheck(dir string) (err error) {
var fi os.FileInfo
if fi, err = os.Stat(dir); err != nil {
if !os.IsExist(err) || os.IsNotExist(err) {
return DirMk(dir)
}
}
if !fi.IsDir() {
err = ErrorIsNotDir
}
return
}
func DirMk(dir string) error {
return os.MkdirAll(dir, 0755)
}
const MaxScanDeep = 20
var maxDeepError = errors.New("scanMaxDeep")
func IsScanMaxDeep(err error) bool {
return errors.Is(err, maxDeepError)
}
// DirScan 扫描目录on err skip
func DirScan(dir string, h func(dir string, info os.FileInfo)) error {
return dirScan(dir, h, 0)
}
func dirScanIgnore(name string) bool {
return strings.HasPrefix(name, ".") ||
strings.Contains(strings.ToLower(name), "readme")
}
func dirScan(dir string, h func(dir string, info os.FileInfo), deep int) error {
if deep > MaxScanDeep {
return maxDeepError
}
dirs, err := os.ReadDir(dir)
if err != nil {
return err
}
var (
info os.FileInfo
nextDir string
)
for _, entry := range dirs {
info, err = entry.Info()
if err != nil {
zap.L().Warn("scan err", zap.String("name", entry.Name()), zap.Error(err))
continue
}
if dirScanIgnore(info.Name()) {
continue
}
h(dir, info)
if entry.IsDir() {
nextDir = filepath.Join(dir, info.Name())
if err = dirScan(nextDir, h, deep+1); err != nil {
zap.L().Warn("scan err", zap.String("dirname", nextDir), zap.Error(err))
}
}
}
return err
}
func PathAbs(path string) string {
if filepath.IsAbs(path) {
return path
}
abs, err := filepath.Abs(path)
if err != nil {
return path
}
return abs
}