-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
9,394 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
github.com/webnice/kit/v3/module/file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Package file | ||
package file | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
) | ||
|
||
// CleanEmptyFolder Удаление пустых папок. | ||
func (fl *impl) CleanEmptyFolder(folderPath string) (err error) { | ||
return fl.cleanEmptyFolderRecursive(folderPath, 0) | ||
} | ||
|
||
// Более удобный для рекурсии вариант функции удаления пустых папок. | ||
func (fl *impl) cleanEmptyFolderRecursive(pt string, level int64) (err error) { | ||
var ( | ||
fi []os.FileInfo | ||
n int | ||
) | ||
|
||
if fi, err = ioutil.ReadDir(pt); err != nil { | ||
err = fmt.Errorf("чтение директории %q прервано ошибкой: %w", pt, err) | ||
return | ||
} | ||
if len(fi) == 0 && level > 0 { | ||
if err = os.Remove(pt); err != nil { | ||
err = fmt.Errorf("удаление директории %q прервано ошибкой: %w", pt, err) | ||
} | ||
return | ||
} | ||
for n = range fi { | ||
switch { | ||
case fi[n].IsDir(): | ||
if err = fl.cleanEmptyFolderRecursive(path.Join(pt, fi[n].Name()), level+1); err != nil { | ||
return | ||
} | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Package file | ||
package file | ||
|
||
import ( | ||
"crypto/sha512" | ||
"encoding/hex" | ||
"fmt" | ||
"hash" | ||
"io" | ||
"os" | ||
) | ||
|
||
// Copy Копирует один файл в другой. | ||
func (fl *impl) Copy(dst string, src string) (size int64, err error) { | ||
const defaultFileMode = os.FileMode(0644) | ||
var ( | ||
inp *os.File | ||
out *os.File | ||
) | ||
|
||
if inp, err = os.Open(src); err != nil { | ||
err = fmt.Errorf("открытие файла %q прервано ошибкой: %w", src, err) | ||
return | ||
} | ||
defer func() { _ = inp.Close() }() | ||
if out, err = os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, defaultFileMode); err != nil { | ||
err = fmt.Errorf("создание файла %q прервано ошибкой: %w", dst, err) | ||
return | ||
} | ||
defer func() { _ = out.Sync(); _ = out.Close() }() | ||
if size, err = io.Copy(out, inp); err != nil { | ||
err = fmt.Errorf("копирование данных из файла %q в файл %q завершилось ошибкой: %w", dst, src, err) | ||
return | ||
} | ||
|
||
return | ||
} | ||
|
||
// CopyWithSha512Sum Копирование контента с параллельным вычислением контрольной суммы алгоритмом SHA512. | ||
func (fl *impl) CopyWithSha512Sum(dst io.Writer, src io.Reader) (written int64, sha512sum string, err error) { | ||
var ( | ||
er, ew error | ||
size, nr, nw int | ||
buf []byte | ||
lr *io.LimitedReader | ||
ok bool | ||
sha hash.Hash | ||
end bool | ||
) | ||
|
||
size = 32 * 1024 | ||
if lr, ok = src.(*io.LimitedReader); ok && int64(size) > lr.N { | ||
if size = int(lr.N); lr.N < 1 { | ||
size = 1 | ||
} | ||
} | ||
buf, sha = make([]byte, size), sha512.New() | ||
for { | ||
if end { | ||
break | ||
} | ||
if nr, er = src.Read(buf); nr > 0 { | ||
if _, err = sha.Write(buf[0:nr]); err != nil { | ||
err = fmt.Errorf("вычисление контрольной суммы sha-512 прервано ошибкой: %w", err) | ||
return | ||
} | ||
if nw, ew = dst.Write(buf[0:nr]); nw > 0 { | ||
written += int64(nw) | ||
} | ||
if ew != nil { | ||
err = ew | ||
break | ||
} | ||
if nr != nw { | ||
err = io.ErrShortWrite | ||
break | ||
} | ||
} | ||
switch er { | ||
case nil: | ||
case io.EOF: | ||
end, er = true, nil | ||
default: | ||
end, err = true, fmt.Errorf("чтение данных прервано ошибкой: %w", er) | ||
} | ||
} | ||
sha512sum = hex.EncodeToString(sha.Sum(nil)) | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Package file | ||
package file | ||
|
||
//go:generate go run mime_generate.go | ||
//go:generate gofmt -w mime.go | ||
|
||
import ( | ||
stdMime "mime" | ||
"os" | ||
"strings" | ||
) | ||
|
||
// Добавление всех mime types | ||
func init() { mimeAddAll() } | ||
|
||
// New creates new object and return Interface | ||
func New() Interface { | ||
var obj = new(impl) | ||
return obj | ||
} | ||
|
||
// Добавление всех mime types | ||
func mimeAddAll() { | ||
const prefix = `.` | ||
var mt string | ||
|
||
for mt = range mimeTypeExtension { | ||
_ = stdMime.AddExtensionType(prefix+mimeTypeExtension[mt], mt) | ||
} | ||
} | ||
|
||
// GetFilename Выделение из полного пути к файлу, имени файла. | ||
func (fl *impl) GetFilename(filename string) (ret string) { | ||
var ch []string | ||
|
||
if ch = strings.Split(filename, string(os.PathSeparator)); len(ch) > 0 { | ||
ret = ch[len(ch)-1] | ||
return | ||
} | ||
ret = filename | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Package file | ||
package file | ||
|
||
import ( | ||
"crypto/sha512" | ||
"encoding/hex" | ||
"fmt" | ||
"hash" | ||
"io" | ||
"os" | ||
) | ||
|
||
// GetInfoSha512 Считывание информации о файле с контрольной суммой. | ||
func (fl *impl) GetInfoSha512(filename string) (inf *InfoSha512, err error) { | ||
const defaultFileMode = 0755 | ||
var ( | ||
fh *os.File | ||
s512 hash.Hash | ||
fi os.FileInfo | ||
) | ||
|
||
inf = new(InfoSha512) | ||
if fh, err = os.OpenFile(filename, os.O_RDONLY, os.FileMode(defaultFileMode)); err != nil { | ||
err = fmt.Errorf("open file %q, error: %s", filename, err) | ||
return | ||
} | ||
defer func() { _ = fh.Close() }() | ||
s512 = sha512.New() | ||
if inf.Size, err = io.Copy(s512, fh); err != nil { | ||
err = fmt.Errorf("чтение файла %q прервано ошибкой: %w", filename, err) | ||
return | ||
} | ||
if fi, err = fh.Stat(); err != nil { | ||
err = fmt.Errorf("получение атрибутов файла %q прервано ошибкой: %w", filename, err) | ||
return | ||
} | ||
if inf.Size != fi.Size() { | ||
err = fmt.Errorf("считан файл размером %d байт, ожидался размер %d байт", fi.Size(), inf.Size) | ||
return | ||
} | ||
inf.Sha512, inf.Name = hex.EncodeToString(s512.Sum(nil)[:]), fl.GetFilename(filename) | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Package file | ||
package file | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
) | ||
|
||
// RecursiveFileList Поиск всех файлов начиная от folderPath рекурсивно. | ||
// Возвращается слайс относительных имён файлов. | ||
func (fl *impl) RecursiveFileList(folderPath string) (ret []string, err error) { | ||
ret, err = fl.recursiveFileListLoop(folderPath, "") | ||
|
||
return | ||
} | ||
|
||
// Удобная для рекурсии функция | ||
func (fl *impl) recursiveFileListLoop(baseFolderPath, currentFolderPath string) (ret []string, err error) { | ||
var ( | ||
pf string | ||
fis []os.FileInfo | ||
n int | ||
) | ||
|
||
pf = path.Join(baseFolderPath, currentFolderPath) | ||
if fis, err = ioutil.ReadDir(pf); err != nil { | ||
return | ||
} | ||
for n = range fis { | ||
switch { | ||
case fis[n].IsDir(): | ||
ret, err = fl.recursiveFileListLoop(baseFolderPath, path.Join(currentFolderPath, fis[n].Name())) | ||
if err != nil { | ||
return | ||
} | ||
case !fis[n].IsDir(): | ||
ret = append(ret, path.Join(currentFolderPath, fis[n].Name())) | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Package file | ||
package file | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"os" | ||
) | ||
|
||
// LoadFile Загрузка файла в память и возврат в виде *bytes.Buffer. | ||
func (fl *impl) LoadFile(filename string) (data *bytes.Buffer, info os.FileInfo, err error) { | ||
const defaultFileMode = os.FileMode(0755) | ||
var fh *os.File | ||
|
||
if fh, err = os.OpenFile(filename, os.O_RDONLY, defaultFileMode); err != nil { | ||
err = fmt.Errorf("открытие файла %q прервано ошибкой: %w", filename, err) | ||
return | ||
} | ||
defer func() { _ = fh.Close() }() | ||
if info, err = fh.Stat(); err != nil { | ||
err = fmt.Errorf("получение атрибутов файла %q прервано ошибкой: %w", filename, err) | ||
return | ||
} | ||
data = new(bytes.Buffer) | ||
if _, err = io.Copy(data, fh); err != nil { | ||
err = fmt.Errorf("чтение данных из файла %q прервано ошибкой: %w", filename, err) | ||
return | ||
} | ||
|
||
return | ||
} |
Oops, something went wrong.