Files
zmkgC/api/v1/common/coryCommon/uploadFile.go
2025-07-07 20:11:59 +08:00

474 lines
13 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 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
}