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 }