330 lines
8.2 KiB
Go
330 lines
8.2 KiB
Go
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
|
||
}
|