pkg/files/file_util.go
2023-09-18 15:58:52 +08:00

154 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package files
import (
"errors"
"io"
"lab.evlic.cn/go/pkg/md5"
"mime/multipart"
"os"
"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
}