feat: 合并Gin_Vue
This commit is contained in:
154
src/framework/utils/file/excel.go
Normal file
154
src/framework/utils/file/excel.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"ems.agt/src/framework/constants/uploadsubpath"
|
||||
"ems.agt/src/framework/logger"
|
||||
"ems.agt/src/framework/utils/date"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
// TransferExeclUploadFile 表格文件上传保存
|
||||
//
|
||||
// file 上传文件对象
|
||||
func TransferExeclUploadFile(file *multipart.FileHeader) (string, error) {
|
||||
// 上传文件检查
|
||||
err := isAllowWrite(file.Filename, []string{".xls", ".xlsx"}, file.Size)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 上传资源路径
|
||||
_, dir := resourceUpload()
|
||||
// 新文件名称并组装文件地址
|
||||
filePath := filepath.Join(uploadsubpath.IMPORT, date.ParseDatePath(time.Now()))
|
||||
fileName := generateFileName(file.Filename)
|
||||
writePathFile := filepath.Join(dir, filePath, fileName)
|
||||
// 存入新文件路径
|
||||
err = transferToNewFile(file, writePathFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.ToSlash(writePathFile), nil
|
||||
}
|
||||
|
||||
// 表格读取数据
|
||||
//
|
||||
// filePath 文件路径地址
|
||||
//
|
||||
// sheetName 工作簿名称, 空字符默认Sheet1
|
||||
func ReadSheet(filePath, sheetName string) ([]map[string]string, error) {
|
||||
data := make([]map[string]string, 0)
|
||||
// 打开 Excel 文件
|
||||
f, err := excelize.OpenFile(filePath)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
logger.Errorf("工作表文件关闭失败 : %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 检查工作簿是否存在
|
||||
if sheetName == "" {
|
||||
sheetName = "Sheet1"
|
||||
}
|
||||
if visible, _ := f.GetSheetVisible(sheetName); !visible {
|
||||
return data, fmt.Errorf("读取工作簿 %s 失败", sheetName)
|
||||
}
|
||||
|
||||
// 获取工作簿记录
|
||||
rows, err := f.GetRows(sheetName)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
|
||||
for i, row := range rows {
|
||||
// 跳过第一行
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
// 遍历每个单元格
|
||||
rowData := map[string]string{}
|
||||
for columnIndex, cellValue := range row {
|
||||
columnName, _ := excelize.ColumnNumberToName(columnIndex + 1)
|
||||
rowData[columnName] = cellValue
|
||||
}
|
||||
|
||||
data = append(data, rowData)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 表格写入数据
|
||||
//
|
||||
// headerCells 第一行表头标题 "A1":"?"
|
||||
//
|
||||
// dataCells 从第二行开始的数据 "A2":"?"
|
||||
//
|
||||
// fileName 文件名称
|
||||
//
|
||||
// sheetName 工作簿名称, 空字符默认Sheet1
|
||||
func WriteSheet(headerCells map[string]string, dataCells []map[string]any, fileName, sheetName string) (string, error) {
|
||||
f := excelize.NewFile()
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
logger.Errorf("工作表文件关闭失败 : %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 创建一个工作表
|
||||
if sheetName == "" {
|
||||
sheetName = "Sheet1"
|
||||
}
|
||||
index, err := f.NewSheet(sheetName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建工作表失败 %v", err)
|
||||
}
|
||||
// 设置工作簿的默认工作表
|
||||
f.SetActiveSheet(index)
|
||||
|
||||
// 首个和最后key名称
|
||||
firstKey := "A"
|
||||
lastKey := "B"
|
||||
|
||||
// 第一行表头标题
|
||||
for key, title := range headerCells {
|
||||
f.SetCellValue(sheetName, key, title)
|
||||
if key[:1] > lastKey {
|
||||
lastKey = key[:1]
|
||||
}
|
||||
}
|
||||
|
||||
// 设置工作表上宽度为 20
|
||||
f.SetColWidth(sheetName, firstKey, lastKey, 20)
|
||||
|
||||
// 从第二行开始的数据
|
||||
for _, cell := range dataCells {
|
||||
for key, value := range cell {
|
||||
f.SetCellValue(sheetName, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// 上传资源路径
|
||||
_, dir := resourceUpload()
|
||||
filePath := filepath.Join(uploadsubpath.EXPORT, date.ParseDatePath(time.Now()))
|
||||
saveFilePath := filepath.Join(dir, filePath, fileName)
|
||||
|
||||
// 创建文件目录
|
||||
if err := os.MkdirAll(filepath.Dir(saveFilePath), 0750); err != nil {
|
||||
return "", fmt.Errorf("创建保存文件失败 %v", err)
|
||||
}
|
||||
|
||||
// 根据指定路径保存文件
|
||||
if err := f.SaveAs(saveFilePath); err != nil {
|
||||
return "", fmt.Errorf("保存工作表失败 %v", err)
|
||||
}
|
||||
return saveFilePath, nil
|
||||
}
|
||||
297
src/framework/utils/file/file.go
Normal file
297
src/framework/utils/file/file.go
Normal file
@@ -0,0 +1,297 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ems.agt/src/framework/config"
|
||||
"ems.agt/src/framework/constants/uploadsubpath"
|
||||
"ems.agt/src/framework/logger"
|
||||
"ems.agt/src/framework/utils/date"
|
||||
"ems.agt/src/framework/utils/generate"
|
||||
"ems.agt/src/framework/utils/parse"
|
||||
"ems.agt/src/framework/utils/regular"
|
||||
)
|
||||
|
||||
/**最大文件名长度 */
|
||||
const DEFAULT_FILE_NAME_LENGTH = 100
|
||||
|
||||
// 文件上传路径 prefix, dir
|
||||
func resourceUpload() (string, string) {
|
||||
upload := config.Get("staticFile.upload").(map[string]any)
|
||||
dir, err := filepath.Abs(upload["dir"].(string))
|
||||
if err != nil {
|
||||
logger.Errorf("file resourceUpload err %v", err)
|
||||
}
|
||||
return upload["prefix"].(string), dir
|
||||
}
|
||||
|
||||
// 最大上传文件大小
|
||||
func uploadFileSize() int64 {
|
||||
fileSize := 1 * 1024 * 1024
|
||||
size := config.Get("upload.fileSize").(int)
|
||||
if size > 1 {
|
||||
fileSize = size * 1024 * 1024
|
||||
}
|
||||
return int64(fileSize)
|
||||
}
|
||||
|
||||
// 文件上传扩展名白名单
|
||||
func uploadWhiteList() []string {
|
||||
arr := config.Get("upload.whitelist").([]any)
|
||||
strings := make([]string, len(arr))
|
||||
for i, val := range arr {
|
||||
if str, ok := val.(string); ok {
|
||||
strings[i] = str
|
||||
}
|
||||
}
|
||||
return strings
|
||||
}
|
||||
|
||||
// 生成文件名称 fileName_随机值.extName
|
||||
//
|
||||
// fileName 原始文件名称含后缀,如:logo.png
|
||||
func generateFileName(fileName string) string {
|
||||
fileExt := filepath.Ext(fileName)
|
||||
// 替换掉后缀和特殊字符保留文件名
|
||||
newFileName := regular.Replace(fileName, fileExt, "")
|
||||
newFileName = regular.Replace(newFileName, `[<>:"\\|?*]+`, "")
|
||||
newFileName = strings.TrimSpace(newFileName)
|
||||
return fmt.Sprintf("%s_%s%s", newFileName, generate.Code(6), fileExt)
|
||||
}
|
||||
|
||||
// 检查文件允许写入本地
|
||||
//
|
||||
// fileName 原始文件名称含后缀,如:midway1_logo_iipc68.png
|
||||
//
|
||||
// allowExts 允许上传拓展类型,['.png']
|
||||
func isAllowWrite(fileName string, allowExts []string, fileSize int64) error {
|
||||
// 判断上传文件名称长度
|
||||
if len(fileName) > DEFAULT_FILE_NAME_LENGTH {
|
||||
return fmt.Errorf("上传文件名称长度限制最长为 %d", DEFAULT_FILE_NAME_LENGTH)
|
||||
}
|
||||
|
||||
// 最大上传文件大小
|
||||
maxFileSize := uploadFileSize()
|
||||
if fileSize > maxFileSize {
|
||||
return fmt.Errorf("最大上传文件大小 %s", parse.Bit(float64(maxFileSize)))
|
||||
}
|
||||
|
||||
// 判断文件拓展是否为允许的拓展类型
|
||||
fileExt := filepath.Ext(fileName)
|
||||
hasExt := false
|
||||
if len(allowExts) == 0 {
|
||||
allowExts = uploadWhiteList()
|
||||
}
|
||||
for _, ext := range allowExts {
|
||||
if ext == fileExt {
|
||||
hasExt = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasExt {
|
||||
return fmt.Errorf("上传文件类型不支持,仅支持以下类型:%s", strings.Join(allowExts, "、"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查文件允许本地读取
|
||||
//
|
||||
// filePath 文件存放资源路径,URL相对地址
|
||||
func isAllowRead(filePath string) error {
|
||||
// 禁止目录上跳级别
|
||||
if strings.Contains(filePath, "..") {
|
||||
return fmt.Errorf("禁止目录上跳级别")
|
||||
}
|
||||
|
||||
// 检查允许下载的文件规则
|
||||
fileExt := filepath.Ext(filePath)
|
||||
hasExt := false
|
||||
for _, ext := range uploadWhiteList() {
|
||||
if ext == fileExt {
|
||||
hasExt = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasExt {
|
||||
return fmt.Errorf("非法下载的文件规则:%s", fileExt)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TransferUploadFile 上传资源文件转存
|
||||
//
|
||||
// subPath 子路径,默认 UploadSubPath.DEFAULT
|
||||
//
|
||||
// allowExts 允许上传拓展类型(含“.”),如 ['.png','.jpg']
|
||||
func TransferUploadFile(file *multipart.FileHeader, subPath string, allowExts []string) (string, error) {
|
||||
// 上传文件检查
|
||||
err := isAllowWrite(file.Filename, allowExts, file.Size)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 上传资源路径
|
||||
prefix, dir := resourceUpload()
|
||||
// 新文件名称并组装文件地址
|
||||
fileName := generateFileName(file.Filename)
|
||||
filePath := filepath.Join(subPath, date.ParseDatePath(time.Now()))
|
||||
writePathFile := filepath.Join(dir, filePath, fileName)
|
||||
// 存入新文件路径
|
||||
err = transferToNewFile(file, writePathFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
urlPath := filepath.Join(prefix, filePath, fileName)
|
||||
return filepath.ToSlash(urlPath), nil
|
||||
}
|
||||
|
||||
// ReadUploadFileStream 上传资源文件读取
|
||||
//
|
||||
// filePath 文件存放资源路径,URL相对地址 如:/upload/common/2023/06/xxx.png
|
||||
//
|
||||
// headerRange 断点续传范围区间,bytes=0-12131
|
||||
func ReadUploadFileStream(filePath, headerRange string) (map[string]any, error) {
|
||||
// 读取文件检查
|
||||
err := isAllowRead(filePath)
|
||||
if err != nil {
|
||||
return map[string]any{}, err
|
||||
}
|
||||
// 上传资源路径
|
||||
prefix, dir := resourceUpload()
|
||||
fileAsbPath := strings.Replace(filePath, prefix, dir, 1)
|
||||
|
||||
// 响应结果
|
||||
result := map[string]any{
|
||||
"range": "",
|
||||
"chunkSize": 0,
|
||||
"fileSize": 0,
|
||||
"data": nil,
|
||||
}
|
||||
|
||||
// 文件大小
|
||||
fileSize := getFileSize(fileAsbPath)
|
||||
if fileSize <= 0 {
|
||||
return result, nil
|
||||
}
|
||||
result["fileSize"] = fileSize
|
||||
|
||||
if headerRange != "" {
|
||||
partsStr := strings.Replace(headerRange, "bytes=", "", 1)
|
||||
parts := strings.Split(partsStr, "-")
|
||||
start, err := strconv.ParseInt(parts[0], 10, 64)
|
||||
if err != nil || start > fileSize {
|
||||
start = 0
|
||||
}
|
||||
end, err := strconv.ParseInt(parts[1], 10, 64)
|
||||
if err != nil || end > fileSize {
|
||||
end = fileSize - 1
|
||||
}
|
||||
if start > end {
|
||||
start = end
|
||||
}
|
||||
|
||||
// 分片结果
|
||||
result["range"] = fmt.Sprintf("bytes %d-%d/%d", start, end, fileSize)
|
||||
result["chunkSize"] = end - start + 1
|
||||
byteArr, err := getFileStream(fileAsbPath, start, end)
|
||||
if err != nil {
|
||||
return map[string]any{}, errors.New("读取文件失败")
|
||||
}
|
||||
result["data"] = byteArr
|
||||
return result, nil
|
||||
}
|
||||
|
||||
byteArr, err := getFileStream(fileAsbPath, 0, fileSize)
|
||||
if err != nil {
|
||||
return map[string]any{}, errors.New("读取文件失败")
|
||||
}
|
||||
result["data"] = byteArr
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// TransferChunkUploadFile 上传资源切片文件转存
|
||||
//
|
||||
// file 上传文件对象
|
||||
//
|
||||
// index 切片文件序号
|
||||
//
|
||||
// identifier 切片文件目录标识符
|
||||
func TransferChunkUploadFile(file *multipart.FileHeader, index, identifier string) (string, error) {
|
||||
// 上传文件检查
|
||||
err := isAllowWrite(file.Filename, []string{}, file.Size)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 上传资源路径
|
||||
prefix, dir := resourceUpload()
|
||||
// 新文件名称并组装文件地址
|
||||
filePath := filepath.Join(uploadsubpath.CHUNK, date.ParseDatePath(time.Now()), identifier)
|
||||
writePathFile := filepath.Join(dir, filePath, index)
|
||||
// 存入新文件路径
|
||||
err = transferToNewFile(file, writePathFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
urlPath := filepath.Join(prefix, filePath, index)
|
||||
return filepath.ToSlash(urlPath), nil
|
||||
}
|
||||
|
||||
// 上传资源切片文件检查
|
||||
//
|
||||
// identifier 切片文件目录标识符
|
||||
//
|
||||
// originalFileName 原始文件名称,如logo.png
|
||||
func ChunkCheckFile(identifier, originalFileName string) ([]string, error) {
|
||||
// 读取文件检查
|
||||
err := isAllowWrite(originalFileName, []string{}, 0)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
// 上传资源路径
|
||||
_, dir := resourceUpload()
|
||||
dirPath := path.Join(uploadsubpath.CHUNK, date.ParseDatePath(time.Now()), identifier)
|
||||
readPath := path.Join(dir, dirPath)
|
||||
fileList, err := getDirFileNameList(readPath)
|
||||
if err != nil {
|
||||
return []string{}, errors.New("读取文件失败")
|
||||
}
|
||||
return fileList, nil
|
||||
}
|
||||
|
||||
// 上传资源切片文件检查
|
||||
//
|
||||
// identifier 切片文件目录标识符
|
||||
//
|
||||
// originalFileName 原始文件名称,如logo.png
|
||||
//
|
||||
// subPath 子路径,默认 DEFAULT
|
||||
func ChunkMergeFile(identifier, originalFileName, subPath string) (string, error) {
|
||||
// 读取文件检查
|
||||
err := isAllowWrite(originalFileName, []string{}, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 上传资源路径
|
||||
prefix, dir := resourceUpload()
|
||||
// 切片存放目录
|
||||
dirPath := path.Join(uploadsubpath.CHUNK, date.ParseDatePath(time.Now()), identifier)
|
||||
readPath := path.Join(dir, dirPath)
|
||||
// 组合存放文件路径
|
||||
fileName := generateFileName(originalFileName)
|
||||
filePath := path.Join(subPath, date.ParseDatePath(time.Now()))
|
||||
writePath := path.Join(dir, filePath)
|
||||
err = mergeToNewFile(readPath, writePath, fileName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
urlPath := filepath.Join(prefix, filePath, fileName)
|
||||
return filepath.ToSlash(urlPath), nil
|
||||
}
|
||||
185
src/framework/utils/file/utils.go
Normal file
185
src/framework/utils/file/utils.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"ems.agt/src/framework/logger"
|
||||
)
|
||||
|
||||
// transferToNewFile 读取目标文件转移到新路径下
|
||||
//
|
||||
// readFilePath 读取目标文件
|
||||
//
|
||||
// writePath 写入路径
|
||||
//
|
||||
// fileName 文件名称
|
||||
func transferToNewFile(file *multipart.FileHeader, dst string) error {
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, src)
|
||||
return err
|
||||
}
|
||||
|
||||
// mergeToNewFile 将多个文件合并成一个文件并删除合并前的切片目录文件
|
||||
//
|
||||
// dirPath 读取要合并文件的目录
|
||||
//
|
||||
// writePath 写入路径
|
||||
//
|
||||
// fileName 文件名称
|
||||
func mergeToNewFile(dirPath string, writePath string, fileName string) error {
|
||||
// 读取目录下所有文件并排序,注意文件名称是否数值
|
||||
fileNameList, err := getDirFileNameList(dirPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取合并目标文件失败: %v", err)
|
||||
}
|
||||
if len(fileNameList) <= 0 {
|
||||
return fmt.Errorf("读取合并目标文件失败")
|
||||
}
|
||||
|
||||
// 排序
|
||||
sort.Slice(fileNameList, func(i, j int) bool {
|
||||
numI, _ := strconv.Atoi(fileNameList[i])
|
||||
numJ, _ := strconv.Atoi(fileNameList[j])
|
||||
return numI < numJ
|
||||
})
|
||||
|
||||
// 写入到新路径文件
|
||||
newFilePath := filepath.Join(writePath, fileName)
|
||||
if err = os.MkdirAll(filepath.Dir(newFilePath), 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 转移完成后删除切片目录
|
||||
defer os.Remove(dirPath)
|
||||
|
||||
// 打开新路径文件
|
||||
outputFile, err := os.Create(newFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create file: %v", err)
|
||||
}
|
||||
defer outputFile.Close()
|
||||
|
||||
// 逐个读取文件后进行流拷贝数据块
|
||||
for _, fileName := range fileNameList {
|
||||
chunkPath := filepath.Join(dirPath, fileName)
|
||||
// 拷贝结束后删除切片
|
||||
defer os.Remove(chunkPath)
|
||||
// 打开切片文件
|
||||
inputFile, err := os.Open(chunkPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file: %v", err)
|
||||
}
|
||||
defer inputFile.Close()
|
||||
// 拷贝文件流
|
||||
_, err = io.Copy(outputFile, inputFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to copy file data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getFileSize 读取文件大小
|
||||
func getFileSize(filePath string) int64 {
|
||||
// 获取文件信息
|
||||
fileInfo, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed stat %s: %v", filePath, err)
|
||||
return 0
|
||||
}
|
||||
// 获取文件大小(字节数)
|
||||
return fileInfo.Size()
|
||||
}
|
||||
|
||||
// 读取文件流用于返回下载
|
||||
//
|
||||
// filePath 文件路径
|
||||
// startOffset, endOffset 分片块读取区间,根据文件切片的块范围
|
||||
func getFileStream(filePath string, startOffset, endOffset int64) ([]byte, error) {
|
||||
// 打开文件
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 获取文件的大小
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileSize := fileInfo.Size()
|
||||
|
||||
// 确保起始和结束偏移量在文件范围内
|
||||
if startOffset > fileSize {
|
||||
startOffset = 0
|
||||
}
|
||||
if endOffset >= fileSize {
|
||||
endOffset = fileSize - 1
|
||||
}
|
||||
|
||||
// 计算切片的大小
|
||||
chunkSize := endOffset - startOffset + 1
|
||||
|
||||
// 创建 SectionReader
|
||||
reader := io.NewSectionReader(file, startOffset, chunkSize)
|
||||
|
||||
// 创建一个缓冲区来存储读取的数据
|
||||
buffer := make([]byte, chunkSize)
|
||||
|
||||
// 读取数据到缓冲区
|
||||
_, err = reader.Read(buffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
// 获取文件目录下所有文件名称,不含目录名称
|
||||
//
|
||||
// filePath 文件路径
|
||||
func getDirFileNameList(dirPath string) ([]string, error) {
|
||||
fileNames := []string{}
|
||||
|
||||
dir, err := os.Open(dirPath)
|
||||
if err != nil {
|
||||
return fileNames, nil
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
fileInfos, err := dir.Readdir(-1)
|
||||
if err != nil {
|
||||
return fileNames, err
|
||||
}
|
||||
|
||||
for _, fileInfo := range fileInfos {
|
||||
if fileInfo.Mode().IsRegular() {
|
||||
fileNames = append(fileNames, fileInfo.Name())
|
||||
}
|
||||
}
|
||||
|
||||
return fileNames, nil
|
||||
}
|
||||
Reference in New Issue
Block a user