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

330 lines
8.2 KiB
Go
Raw Normal View History

2025-07-07 20:11:59 +08:00
package coryCommon
import (
"archive/zip"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/tiger1103/gfast/v3/internal/app/system/model"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
// CreateZipFile 生成一个压缩文件夹,然后将指定文件夹的数据(文件及文件夹)存放到压缩文件下
func CreateZipFile(sourceDir, zipFile string) error {
zipFileToCreate, err := os.Create(zipFile)
if err != nil {
return err
}
defer zipFileToCreate.Close()
zipWriter := zip.NewWriter(zipFileToCreate)
defer zipWriter.Close()
err = filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
return addFileToZip(zipWriter, path, sourceDir)
})
if err != nil {
return err
}
return nil
}
func addFileToZip(zipWriter *zip.Writer, filePath, baseDir string) error {
fileToZip, err := os.Open(filePath)
if err != nil {
return err
}
defer fileToZip.Close()
info, err := fileToZip.Stat()
if err != nil {
return err
}
// 获取文件相对路径
relPath, err := filepath.Rel(baseDir, filePath)
if err != nil {
return err
}
// 替换路径分隔符确保在压缩文件中使用正斜杠
relPath = strings.ReplaceAll(relPath, `\`, "/")
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = relPath
if info.IsDir() {
header.Name += "/"
header.Method = zip.Store // Directory
} else {
header.Method = zip.Deflate // File
}
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
if !info.IsDir() {
_, err = io.Copy(writer, fileToZip)
if err != nil {
return err
}
}
return nil
}
// MultifileDownload 【功能:多文件下载】===【参数relativelyTemporaryPath相对路径、filesToCopy需要放在压缩包下载的文件】
func MultifileDownload(relativelyTemporaryPath string, filesToCopy []string) (path string, err error) {
//网络资源下载到本地
for i := range filesToCopy {
url := filesToCopy[i]
pathParts := strings.Split(url, "/")
fileName := pathParts[len(pathParts)-1]
filePath := filepath.ToSlash(GetCWD() + Temporary + "/" + fileName)
err = DownloadFile(url, filePath)
if err != nil {
return "", err
}
filesToCopy[i] = filePath
}
// 1、创建临时压缩包
zipFile, zipWriter, err := createTempZip(relativelyTemporaryPath)
if err != nil {
fmt.Println("Error creating temp zip:", err)
return "", err
}
defer func() {
zipWriter.Close()
zipFile.Close()
//暂时不删除、创建了个每月定时清除临时文件的定时器
//for i := range filesToCopy {
// delFile(filesToCopy[i], 0) //删除临时文件
//}
//go delFile(zipFile.Name(), 20) // 删除临时压缩文件20秒后执行防止文件还没下载完成就给删除了
}()
// 2、复制文件夹到压缩包
for _, filePath := range filesToCopy {
err := copyFileToZip(zipWriter, filePath)
if err != nil {
fmt.Printf("Error copying %s to zip: %s\n", filePath, err)
return "", err
}
}
path = strings.ReplaceAll(filepath.ToSlash(zipFile.Name()), filepath.ToSlash(GetCWD())+"/resource/public", "/file") //如果服务器同步需要注意wxfile
return
}
// 创建临时压缩包,并且提供写入数据
func createTempZip(relativelyTemporaryPath string) (*os.File, *zip.Writer, error) {
cwd := GetCWD() + relativelyTemporaryPath
zipFile, err := os.CreateTemp(cwd, "temp_zip_*.zip") //*自动分配
if err != nil {
return nil, nil, err
}
zipWriter := zip.NewWriter(zipFile)
return zipFile, zipWriter, nil
}
// 复制文件到压缩包
func copyFileToZip(zipWriter *zip.Writer, filePath string) error {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
// 获取文件信息
info, err := file.Stat()
if err != nil {
return err
}
// 创建zip文件中的文件头
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
// 指定文件名
header.Name = filepath.Base(filePath)
// 创建zip文件中的文件
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
// 复制文件内容到zip文件中
_, err = io.Copy(writer, file)
return err
}
// delFile 删除文件
func delFile(file string, second int) {
if second > 0 {
time.Sleep(time.Duration(second) * time.Second)
}
if err := os.Remove(file); err != nil {
fmt.Println("Failed to delete temporary file:", err)
}
}
// DownloadFile URL资源下载到自定位置
func DownloadFile(url, localPath string) error {
// 发起HTTP GET请求
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// 检查响应状态码
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("HTTP request failed with status code: %d", resp.StatusCode)
}
// 创建本地文件
file, err := os.Create(localPath)
if err != nil {
return err
}
defer file.Close()
// 将HTTP响应体的内容拷贝到本地文件
_, err = io.Copy(file, resp.Body)
if err != nil {
return err
}
return nil
}
// RemoveAllFilesInDirectory 删除指定目录下的所有文件 例子:"D:\\Cory\\go\\中煤\\zmkg-back\\resource\\public\\temporary"
func RemoveAllFilesInDirectory(directoryPath string) error {
// 获取指定目录下的所有文件和子目录
files, err := filepath.Glob(filepath.Join(directoryPath, "*"))
if err != nil {
return err
}
// 遍历所有文件并删除
for _, file := range files {
if err := os.RemoveAll(file); err != nil {
return err
}
fmt.Println("Deleted:", file)
}
return nil
}
// GetFiles 获取目录下所有文件(包括文件夹中的文件)
func GetFiles(folder string) (filesList []string) {
files, _ := ioutil.ReadDir(folder)
for _, file := range files {
if file.IsDir() {
GetFiles(folder + "/" + file.Name())
} else {
filesList = append(filesList, file.Name())
}
}
return
}
// GetAllFile 获取目录下直属所有文件(不包括文件夹及其中的文件)
func GetAllFile(pathname string) (s []string, err error) {
rd, err := ioutil.ReadDir(pathname)
if err != nil {
fmt.Println("read dir fail:", err)
return s, err
}
for _, fi := range rd {
if !fi.IsDir() {
fullName := pathname + "/" + fi.Name()
s = append(s, fullName)
}
}
return s, nil
}
// Xcopy 复制文件
func Xcopy(source, target string) (err error) {
// 打开源文件
sourceFile, err := os.Open(source)
if err != nil {
return err
}
defer sourceFile.Close()
// 创建目标文件
destinationFile, err := os.Create(target)
if err != nil {
return err
}
defer destinationFile.Close()
// 使用 io.Copy() 函数复制文件内容
_, err = io.Copy(destinationFile, sourceFile)
return err
}
// CustomizationMultifileDownload 定制下载(安全考试专用)
func CustomizationMultifileDownload(relativelyTemporaryPath string, mw []*model.ModelWeChatPdfWoRes) (path string, err error) {
//1、创建文件夹
paht := filepath.ToSlash(GetCWD() + "/" + Ynr(Temporary+"/"))
folder := paht + FileName("aqks") //文件夹名
folder = filepath.ToSlash(folder)
folder = folder[0 : len(folder)-1]
err = os.MkdirAll(folder, 0777)
if err != nil {
return
}
//2、网络资源下载到本地
for i := range mw {
url := mw[i].Path
str := folder + "/" + mw[i].UserName + mw[i].Openid
os.MkdirAll(str, 0777) //根据名字创建子目录
//url看看是几个文件
fileNum := strings.Split(url, ",")
for j := range fileNum {
if fileNum[j] != "" {
//因为pdf是另外一个服务器所以需要下载但是有的又是本地服务器所以直接复制
if strings.Contains(fileNum[j], "/wxfile/") {
pathstr := g.Cfg().MustGet(gctx.New(), "cory").String() + fileNum[j]
pathParts := strings.Split(pathstr, "/")
filePath := str + "/" + pathParts[len(pathParts)-1]
err = DownloadFile(pathstr, filePath) //下载网络图片
if err != nil {
return "", err
}
} else {
source := FileToFunc(fileNum[j], 2)
pathParts := strings.Split(fileNum[j], "/")
target := str + "/" + pathParts[len(pathParts)-1]
err := Xcopy(source, target)
if err != nil {
return "", err
}
}
}
}
}
//3、压缩成压缩包zip
path = paht + FileName("aqks") + ".zip"
err = CreateZipFile(folder, path)
return
}