func (l *LocalStorage) Files(DirectoryPath string) (files []FileInfo, err error) {
	DirectoryFullPath := path.Join(l.rootFolder, DirectoryPath)
	_, err = os.Stat(DirectoryFullPath)
	if os.IsNotExist(err) {
		return []FileInfo{}, err
	}
	res, err := ioutil.ReadDir(DirectoryFullPath)
	for _, val := range res {
		if !val.IsDir() {
			p := path.Join(DirectoryPath, val.Name())
			f, _ := l.FileInfo(p)
			files = append(files, f)
		}
	}
	return files, err
}
Files returns a list of files in a given directory,
the file type is LocalStorage.FileInfo
NOT the standard library fs.FileInfo,
and it returns an error incase any occurred,
if you want a list of files including
the files in sub directories, consider using the method
`AllFiles(DirectoryPath string)`
package localstorage
import (
	"errors"
	"io"
	"io/fs"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
	"unicode/utf8"
)
type LocalStorage struct {
	rootFolder string
}
type FileInfo struct {
	Name                 string
	NameWithoutExtension string
	LastModified         time.Time
	Size                 int64
	Extension            string
	Path                 string
	IsDirectory          bool
	FsFileInfo           fs.FileInfo  
}
var local *LocalStorage
func New(path string) *LocalStorage {
	local = &LocalStorage{
		rootFolder: path,
	}
	return local
}
func (l *LocalStorage) FileInfo(filepath string) (fileinfo FileInfo, err error) {
	fullpath := path.Join(l.rootFolder, filepath)
	if _, err := os.Stat(fullpath); os.IsNotExist(err) {
		return FileInfo{}, errors.New("file does not exist")
	} else if err != nil {
		return FileInfo{}, err
	}
	info, err := os.Stat(fullpath)
	fileinfo = FileInfo{
		Name:                 info.Name(),
		Extension:            removeFirstChar(path.Ext(fullpath)),
		NameWithoutExtension: removeExtension(info.Name(), path.Ext(fullpath)),
		Size:                 info.Size(),
		Path:                 path.Dir(fullpath),
		LastModified:         info.ModTime(),
		IsDirectory:          info.IsDir(),
		FsFileInfo:           info,
	}
	return fileinfo, nil
}
func (l *LocalStorage) Put(filePath string) error {
	s, err := os.Stat(filePath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	_, err = os.Stat(path.Join(l.rootFolder, s.Name()))
	if err == nil {
		return errors.New("the file is already exists")
	}
	srcFile, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	destFile, err := os.Create(path.Join(l.rootFolder, s.Name()))
	if err != nil {
		return err
	}
	defer destFile.Close()
	buf := make([]byte, 100)
	for {
		n, err := srcFile.Read(buf)
		if err != nil && err != io.EOF {
			return err
		}
		if n == 0 {
			break
		}
		if _, err := destFile.Write(buf[:n]); err != nil {
			return err
		}
	}
	return err
}
func (l *LocalStorage) PutAs(filePath string, filename string) error {
	s, err := os.Stat(filePath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	_, err = os.Stat(path.Join(l.rootFolder, filename))
	if err == nil {
		return errors.New("the file is already exists")
	}
	srcFile, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	destFile, err := os.Create(path.Join(l.rootFolder, filename))
	if err != nil {
		return err
	}
	defer destFile.Close()
	buf := make([]byte, 100)
	for {
		n, err := srcFile.Read(buf)
		if err != nil && err != io.EOF {
			return err
		}
		if n == 0 {
			break
		}
		if _, err := destFile.Write(buf[:n]); err != nil {
			return err
		}
	}
	return err
}
func (l *LocalStorage) Copy(filePath string, destPath string) error {
	filePath = filepath.ToSlash(filePath)
	destPath = filepath.ToSlash(destPath)
	srcFileFullPath := filepath.Join(l.rootFolder, filePath)
	DestFullPath := filepath.Join(l.rootFolder, destPath)
	os.MkdirAll(DestFullPath, 0755)
	s, err := os.Stat(srcFileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	_, err = os.Stat(path.Join(DestFullPath, s.Name()))
	if err == nil {
		return errors.New("the file already exists in dest folder")
	}
	srcFile, err := os.Open(srcFileFullPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	destFile, err := os.Create(path.Join(DestFullPath, s.Name()))
	if err != nil {
		return err
	}
	defer destFile.Close()
	_, err = io.Copy(destFile, srcFile)
	if err != nil {
		return err
	}
	return nil
}
func (l *LocalStorage) CopyAs(filePath string, destfolder string, newFilePath string) error {
	filePath = filepath.ToSlash(filePath)
	destfolder = filepath.ToSlash(destfolder)
	srcFileFullPath := filepath.Join(l.rootFolder, filePath)
	DestFileFullPath := filepath.Join(l.rootFolder, destfolder)
	os.MkdirAll(DestFileFullPath, 0755)
	s, err := os.Stat(srcFileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	_, err = os.Stat(path.Join(DestFileFullPath, newFilePath))
	if err == nil {
		return errors.New("the file is already exists")
	}
	srcFile, err := os.Open(srcFileFullPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	destFile, err := os.Create(path.Join(DestFileFullPath, newFilePath))
	if err != nil {
		return err
	}
	defer destFile.Close()
	buf := make([]byte, 100)
	for {
		n, err := srcFile.Read(buf)
		if err != nil && err != io.EOF {
			return err
		}
		if n == 0 {
			break
		}
		if _, err := destFile.Write(buf[:n]); err != nil {
			return err
		}
	}
	return err
}
func (l *LocalStorage) Move(filePath string, destFolder string) error {
	filePath = filepath.ToSlash(filePath)
	destFolder = filepath.ToSlash(destFolder)
	srcFileFullPath := filepath.Join(l.rootFolder, filePath)
	DestFileFullPath := filepath.Join(l.rootFolder, destFolder)
	os.MkdirAll(DestFileFullPath, 0755)
	s, err := os.Stat(srcFileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	_, err = os.Stat(path.Join(DestFileFullPath, s.Name()))
	if err == nil {
		return errors.New("the file is already exists")
	}
	srcFile, err := os.Open(srcFileFullPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	destFile, err := os.Create(path.Join(DestFileFullPath, s.Name()))
	if err != nil {
		return err
	}
	defer destFile.Close()
	buf := make([]byte, 100)
	for {
		n, err := srcFile.Read(buf)
		if err != nil && err != io.EOF {
			return err
		}
		if n == 0 {
			break
		}
		if _, err := destFile.Write(buf[:n]); err != nil {
			return err
		}
	}
	srcFile.Close()
	os.Remove(srcFileFullPath)
	return err
}
func (l *LocalStorage) MoveAs(filePath string, destFolder string, newFilePath string) error {
	filePath = filepath.ToSlash(filePath)
	destFolder = filepath.ToSlash(destFolder)
	srcFileFullPath := filepath.Join(l.rootFolder, filePath)
	DestFileFullPath := filepath.Join(l.rootFolder, destFolder)
	os.MkdirAll(DestFileFullPath, 0755)
	s, err := os.Stat(srcFileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	_, err = os.Stat(path.Join(DestFileFullPath, newFilePath))
	if !os.IsNotExist(err) {
		return errors.New("the file is already exists")
	}
	srcFile, err := os.Open(srcFileFullPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	destFile, err := os.Create(path.Join(DestFileFullPath, newFilePath))
	if err != nil {
		return err
	}
	defer destFile.Close()
	buf := make([]byte, 100)
	for {
		n, err := srcFile.Read(buf)
		if err != nil && err != io.EOF {
			return err
		}
		if n == 0 {
			break
		}
		if _, err := destFile.Write(buf[:n]); err != nil {
			return err
		}
	}
	srcFile.Close()
	os.Remove(srcFileFullPath)
	return err
}
func (l *LocalStorage) Rename(filePath string, newFilePath string) error {
	srcFileFullPath := filepath.Join(l.rootFolder, filePath)
	destFileFullPath := filepath.Join(l.rootFolder, newFilePath)
	s, err := os.Stat(srcFileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	err = os.Rename(srcFileFullPath, destFileFullPath)
	return err
}
func (l *LocalStorage) Delete(filePath string) error {
	srcFileFullPath := filepath.Join(l.rootFolder, filePath)
	s, err := os.Stat(srcFileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	if !s.Mode().IsRegular() {
		return errors.New("File is not in regular mode")
	}
	os.Remove(srcFileFullPath)
	return err
}
func (l *LocalStorage) DeleteMultiple(filePaths []string) (err error) {
	for _, file := range filePaths {
		srcFileFullPath := filepath.Join(l.rootFolder, file)
		s, err := os.Stat(srcFileFullPath)
		if os.IsNotExist(err) {
			continue
		}
		if !s.Mode().IsRegular() {
			continue
		}
		os.Remove(srcFileFullPath)
	}
	return err
}
func (l *LocalStorage) Create(filePath string, content []byte) error {
	fileFullPath := path.Join(l.rootFolder, filePath)
	fileFullPath = filepath.ToSlash(fileFullPath)
	os.MkdirAll(path.Dir(fileFullPath), 0755)
	_, err := os.Stat(fileFullPath)
	if err == nil {
		return errors.New("file already exists")
	}
	file, err := os.Create(fileFullPath)
	if err != nil {
		return err
	}
	_, err = file.Write(content)
	file.Close()
	return err
}
func (l *LocalStorage) Append(filePath string, content []byte) error {
	fileFullPath := path.Join(l.rootFolder, filePath)
	_, err := os.Stat(fileFullPath)
	if os.IsNotExist(err) {
		return err
	}
	file, err := os.OpenFile(fileFullPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = file.Write(content)
	return err
}
func (l *LocalStorage) Exists(filePath string) (bool, error) {
	fileFullPath := path.Join(l.rootFolder, filePath)
	_, err := os.Stat(fileFullPath)
	if os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}
	return true, nil
}
func (l *LocalStorage) Missing(filePath string) (bool, error) {
	fileFullPath := path.Join(l.rootFolder, filePath)
	_, err := os.Stat(fileFullPath)
	if err != nil {
		if os.IsNotExist(err) {
			return true, nil
		}
		return false, err
	}
	return false, nil
}
func (l *LocalStorage) Read(filePath string) ([]byte, error) {
	fileFullPath := path.Join(l.rootFolder, filePath)
	_, err := os.Stat(fileFullPath)
	if os.IsNotExist(err) {
		return nil, err
	}
	content, err := ioutil.ReadFile(fileFullPath)
	if err != nil {
		return nil, err
	}
	return content, nil
}