Files
zmkgC/api/v1/common/coryCommon/uploadFile.go

474 lines
13 KiB
Go
Raw Normal View History

2025-07-07 20:11:59 +08:00
package coryCommon
import (
"bufio"
"context"
"fmt"
"io"
"log"
"net/url"
"os"
"path/filepath"
"strings"
"time"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/tiger1103/gfast/v3/library/liberr"
"golang.org/x/exp/rand"
)
func UploadFileS(ctx context.Context, fileHeader []*ghttp.UploadFile, fileUrl string, typeStr string) (pathStr string, err error) {
for i := range fileHeader {
var str string
if typeStr == "1" {
str, err = UploadFile(ctx, fileHeader[i], fileUrl)
}
if typeStr == "2" {
str, err = UploadFileTwo(ctx, fileHeader[i], fileUrl)
}
if err != nil {
liberr.ErrIsNil(ctx, err)
return
}
pathStr = pathStr + ResourcePublicToFunc("/"+str, 0) + ","
}
pathStr = pathStr[0 : len(pathStr)-1]
return
}
// UploadFile [文件名称为原来的文件名称] 上传文件(流) 也可以将http图片上传 返回:resource/public/upload_file/2023-11-28/tmp_c7858f0fd98d74cbe2c095125871aaf19c749c209ae33f5f.png
func UploadFile(ctx context.Context, fileHeader *ghttp.UploadFile, fileUrl string) (str string, err error) {
// 获取上传的文件流
if fileHeader == nil {
log.Println("Failed to get file")
liberr.ErrIsNil(ctx, err, "Failed to get file")
return "", err
}
ynr := Ynr(fileUrl)
// 在当前目录创建一个新文件用于保存上传的数据
lj := "/" + ynr + fileHeader.Filename
destFilePath := filepath.Join(".", lj)
destFile, err := os.Create(destFilePath)
if err != nil {
log.Println("Failed to create destination file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
defer destFile.Close()
// 创建一个内存缓冲区作为文件数据的临时存储
buffer := make([]byte, 4096)
// 记录已接收的数据量,用于计算上传进度
var totalReceived int64
// 获取文件上传的数据流
file, err := fileHeader.Open()
if err != nil {
log.Println("Failed to open file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
defer file.Close()
// 循环读取文件流,直到读取完整个文件
for {
// 从文件流中读取数据到缓冲区
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
log.Println("Failed to read file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
// 如果缓冲区没有数据,则表示已读取完整个文件
if n == 0 {
break
}
// 将缓冲区的数据写入目标文件
_, err = destFile.Write(buffer[:n])
if err != nil {
log.Println("Failed to write file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
// 更新已接收的数据量
totalReceived += int64(n)
}
//// 返回上传文件的路径给客户端
//uploadPath, err := filepath.Abs(destFilePath)
//if err != nil {
// log.Println("Failed to get absolute file path:", err)
// liberr.ErrIsNil(ctx, err)
// return "", err
//}
//统一路径斜杠为/
str = filepath.ToSlash(lj)
return str, err
}
func UploadUniqueFile(ctx context.Context, fileHeader *ghttp.UploadFile, fileUrl string) (str string, err error) {
// 获取上传的文件流
if fileHeader == nil {
return "", err
}
ynr := Ynr(fileUrl)
// 在当前目录创建一个新文件用于保存上传的数据
// 在文件名中添加一个唯一的标识符,例如当前的时间戳
lj := fmt.Sprintf("%s_%d_%s", ynr, time.Now().Unix(), fileHeader.Filename)
destFilePath := filepath.Join(".", lj)
destFile, err := os.Create(destFilePath)
if err != nil {
log.Println("Failed to create destination file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
defer destFile.Close()
// 创建一个内存缓冲区作为文件数据的临时存储
buffer := make([]byte, 4096)
// 记录已接收的数据量,用于计算上传进度
var totalReceived int64
// 获取文件上传的数据流
file, err := fileHeader.Open()
if err != nil {
log.Println("Failed to open file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
defer file.Close()
// 循环读取文件流,直到读取完整个文件
for {
// 从文件流中读取数据到缓冲区
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
return "", err
}
// 如果缓冲区没有数据,则表示已读取完整个文件
if n == 0 {
break
}
// 将缓冲区的数据写入目标文件
_, err = destFile.Write(buffer[:n])
if err != nil {
return "", err
}
// 更新已接收的数据量
totalReceived += int64(n)
}
// 统一路径斜杠为/
str = filepath.ToSlash(lj)
return str, err
}
// UploadFileTwo [文件名称为时间戳] 上传文件(流) 也可以将http图片上传 返回:resource/public/upload_file/2023-11-28/tmp_c7858f0fd98d74cbe2c095125871aaf19c749c209ae33f5f.png
func UploadFileTwo(ctx context.Context, fileHeader *ghttp.UploadFile, fileUrl string) (str string, err error) {
// 获取上传的文件流
if fileHeader == nil {
log.Println("Failed to get file")
liberr.ErrIsNil(ctx, err, "Failed to get file")
return "", err
}
ynr := Ynr(fileUrl)
// 在当前目录创建一个新文件用于保存上传的数据
lj := /* "/" +*/ ynr + FileName("login") + filepath.Ext(fileHeader.Filename)
destFilePath := filepath.Join(".", lj)
destFile, err := os.Create(destFilePath)
if err != nil {
log.Println("Failed to create destination file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
defer destFile.Close()
// 创建一个内存缓冲区作为文件数据的临时存储
buffer := make([]byte, 4096)
// 记录已接收的数据量,用于计算上传进度
var totalReceived int64
// 获取文件上传的数据流
file, err := fileHeader.Open()
if err != nil {
log.Println("Failed to open file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
defer file.Close()
// 循环读取文件流,直到读取完整个文件
for {
// 从文件流中读取数据到缓冲区
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
log.Println("Failed to read file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
// 如果缓冲区没有数据,则表示已读取完整个文件
if n == 0 {
break
}
// 将缓冲区的数据写入目标文件
_, err = destFile.Write(buffer[:n])
if err != nil {
log.Println("Failed to write file:", err)
liberr.ErrIsNil(ctx, err)
return "", err
}
// 更新已接收的数据量
totalReceived += int64(n)
}
//// 返回上传文件的路径给客户端
//uploadPath, err := filepath.Abs(destFilePath)
//if err != nil {
// log.Println("Failed to get absolute file path:", err)
// liberr.ErrIsNil(ctx, err)
// return "", err
//}
//统一路径斜杠为/
str = filepath.ToSlash(lj)
return str, err
}
// Ynr 创建时间文件夹 传递相对路径/resource/public/ 返回相对路径resource/public/2023-11-12/
func Ynr(baseDir string) (str string) {
// 获取当前时间
currentTime := time.Now()
// 格式化为年月日的字符串格式
dateString := currentTime.Format("2006-01-02")
dateString = baseDir + dateString
// 在相对路径上添加文件夹
destFilePath := filepath.Join(".", dateString)
dateString = destFilePath
// 检查文件夹是否已存在
_, err := os.Stat(dateString)
if os.IsNotExist(err) {
// 文件夹不存在,创建文件夹
err := os.MkdirAll(dateString, os.ModePerm)
if err != nil {
fmt.Println("创建文件夹失败:", err)
return
}
// fmt.Println("文件夹创建成功:", dateString)
} else {
// fmt.Println("文件夹已存在:", dateString)
}
return dateString + "/"
}
// FileName 【前缀】+获取当前时间+随机数得到文件名
func FileName(prefix string) (uniqueFileName string) {
currentTime := time.Now()
timestamp := currentTime.UnixNano() / int64(time.Millisecond)
randomNum := rand.Intn(1000)
uniqueFileName = fmt.Sprintf("%d_%d", timestamp, randomNum)
if prefix != "" {
uniqueFileName = prefix + uniqueFileName
}
return uniqueFileName
}
// FileInfo 传参:相对路径 获取文件信息(文件名称、文件后缀、文件大小(字节))
func FileInfo(filePath string) (name string, ext string, size int64) {
newPath := ""
if strings.Contains(filePath, "wxfile") {
newPath = strings.ReplaceAll(filePath, "/wxfile", GetCWD()+"/resource/public")
} else {
newPath = strings.ReplaceAll(filePath, "/file", GetCWD()+"/resource/public")
}
newPath = strings.ReplaceAll(newPath, "\\", "/")
filePath = newPath
// filePath = "D:\\Cory\\go\\中煤\\zmkg-back\\resource\\public\\upload_file\\2023-08-31\\cv6kxb89pd984rt5ze.png"
// 获取文件的基本名称(包括扩展名)
fileName := filepath.Base(filePath)
// 分割文件名和扩展名
nameParts := strings.Split(fileName, ".")
fileNameWithoutExt := nameParts[0]
fileExt := nameParts[1]
// 获取文件大小
fileInfo, err := os.Stat(filePath)
if err != nil {
fmt.Println("无法获取文件信息:", err)
return
}
fileSize := fileInfo.Size()
// 文件名称、文件后缀、文件大小(字节)
name = fileNameWithoutExt
ext = fileExt
size = fileSize
return
}
// OutJson 创建txt写入数据jsonData数据、absPath 绝对路径(带文件名和后缀)
func OutJson(jsonData []byte, absPath string) (flag bool, err error) {
absPath = strings.ReplaceAll(absPath, "\\", "/")
absPath = strings.ReplaceAll(absPath, "/file", GetCWD()+"/resource/public")
flag = false
// 创建要写入的文件
file, err := os.Create(absPath)
if err != nil {
fmt.Println("无法创建文件:", err)
return
}
defer file.Close()
// 将 JSON 数据写入文件
_, err = file.Write(jsonData)
if err != nil {
fmt.Println("无法写入文件:", err)
return
}
return true, err
}
// PutJson 读取文件
func PutJson(filePath string) (jsonData string, err error) {
filePath = strings.ReplaceAll(filePath, "/file", GetCWD()+"/resource/public")
filePath = strings.ReplaceAll(filePath, "\\", "/")
// filePath := "relative/path/to/file.txt"
file, err := os.Open(filePath)
if err != nil {
fmt.Println("打开文件错误:", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
// 设置一个足够大的缓冲区
const maxScanTokenSize = 128 * 1024
buf := make([]byte, maxScanTokenSize)
scanner.Buffer(buf, maxScanTokenSize)
for scanner.Scan() {
line := scanner.Text()
jsonData = jsonData + line
}
if scanner.Err() != nil {
fmt.Println("读取文件错误:", scanner.Err())
err = scanner.Err()
return
}
return
}
/*
BatchFile 批量刪除文件
filePath 相对路径
*/
func BatchFile(filePath []string) {
for _, data := range filePath {
// if strings.Contains(data, "file") || strings.Contains(data, "wxfile"){
newPath := ""
if strings.Contains(data, "/file") {
newPath = strings.Replace(data, "/file", GetCWD()+"/resource/public", 1)
} else if strings.Contains(data, "/wxfile") {
newPath = strings.Replace(data, "/wxfile", GetCWD()+"/resource/public", 1)
}
os.Remove(strings.ReplaceAll(newPath, "\\", "/"))
}
}
// FlagImg 判斷是否是圖片
func FlagImg(filePath string) (flag bool) {
filePathLower := strings.ToLower(filePath)
isImage := strings.HasSuffix(filePathLower, ".png") || strings.HasSuffix(filePathLower, ".jpg") || strings.HasSuffix(filePathLower, ".jpeg") || strings.HasSuffix(filePathLower, ".gif") || strings.HasSuffix(filePathLower, ".bmp")
if isImage {
flag = true
} else {
flag = false
}
return flag
}
// CreateDirectory 判断文件夹是否存在,不存在则创建文件夹
func CreateDirectory(folderName string) error {
// 检查文件夹是否已经存在
_, err := os.Stat(folderName)
if err == nil {
return nil
}
// 创建文件夹
err = os.Mkdir(folderName, 0o755)
if err != nil {
return err
}
return nil
}
// FileToFunc file转resource/public
func FileToFunc(path string, num int) (rpath string) {
if num == 1 {
rpath = strings.Replace(path, GetCWD()+"/file/", "/resource/public/", 1)
} else if num == 2 {
rpath = strings.Replace(path, "/file/", GetCWD()+"/resource/public/", 1)
} else if num == 3 {
rpath = strings.Replace(path, "/file/", "/wxfile/", 1)
} else if num == 4 {
rpath = strings.Replace(path, "/wxfile/", GetCWD()+"/resource/public/", 1)
} else if num == 5 {
rpath = strings.Replace(path, "/wxfile/", "/file/", 1)
} else {
rpath = strings.Replace(path, "/file/", "/resource/public/", 1)
}
rpath = filepath.ToSlash(rpath)
return
}
// ResourcePublicToFunc resource/public转file
func ResourcePublicToFunc(path string, num int) (rpath string) {
if num == 1 {
rpath = strings.Replace(path, GetCWD()+"/resource/public/", "/file/", 1)
} else if num == 2 {
rpath = strings.Replace(path, "/resource/public/", GetCWD()+"/resource/public/", 1)
} else if num == 3 {
rpath = strings.Replace(path, "/resource/public/", "/wxfile/", 1)
} else {
rpath = strings.Replace(path, "/resource/public/", "/file/", 1)
}
rpath = filepath.ToSlash(rpath)
return
}
// FormatRestrictionFunc 判断文件后缀是否匹配
func FormatRestrictionFunc(path, suffix string) (flag bool) {
split := strings.Split(suffix, ",")
for _, data := range split {
extension := filepath.Ext(path)
if extension == data {
return true
}
}
return false
}
// URLCoding 对url的特俗符号进行编码不对/进行编码(定制编码,将"/file/networkDisk/completion/admin37/2.jpg"的"networkDisk/completion/admin37/2.jpg"进行编码)
func URLCoding(path string) (filenPathCoding string) {
s2 := path[6 : len(path)-1]
split := strings.Split(s2, "/")
p := ""
for i2 := range split {
p = p + url.PathEscape(split[i2]) + "/"
}
p = p[0 : len(p)-1]
filenPathCoding = strings.ReplaceAll(path, s2, p)
return
}