package v1 import ( "context" "designs/app/common/request" "designs/global" "designs/model" "designs/response" "fmt" "github.com/gin-gonic/gin" "github.com/tencentyun/cos-go-sdk-v5" "net/http" "net/url" "os" "path/filepath" "strings" "time" ) func FileList(c *gin.Context) { form := request.Check(c, &struct { Dir string `form:"dir" binding:"required"` Offset *int `form:"offset" binding:"required"` Limit *int `form:"limit" binding:"required"` Search string `form:"search" binding:""` }{}) query := global.App.DB.Table("file").Where("dir", form.Dir) if form.Search != "" { query = query.Where("fileName", "like", "%"+form.Search+"%") } var count int64 err := query.Count(&count).Error if err != nil { response.Fail(c, 1001, err.Error()) return } var files []model.File err = query.Offset(*form.Offset).Limit(*form.Limit).Scan(&files).Error if err != nil { response.Fail(c, 1002, err.Error()) return } response.Success(c, gin.H{ "count": count, "data": files, }) } func DirDownload(c *gin.Context) { form := request.Check(c, &struct { Dir string `form:"dir" binding:"required"` }{}) data, err := DirExplode(form.Dir) if err != nil { response.Fail(c, 1001, err.Error()) return } response.Success(c, gin.H{ "data": data, }) } func DirExplode(dir string) (map[string]interface{}, error) { data := make(map[string]interface{}) var files []model.File err := global.App.DB.Table("file").Where("dir", dir).Scan(&files).Error if err != nil { return nil, err } for _, file := range files { if file.Type == 2 { data[file.FileName], _ = DirExplode(file.Dir) } else { data[file.FileName] = file.CosPath } } return data, nil } func FileDelete(c *gin.Context) { form := request.Check(c, &struct { FileId int `form:"fileId" json:"fileId" binding:"required"` }{}) var file model.File global.App.DB.Table("file").Where("id", form.FileId).Find(&file) if file.Type == 1 { //删除本地文件和云端文件 (本地文件暂时不删除,作为备份) err := ServiceFileDelete(file.CosPath) if err != nil { response.Fail(c, 2001, "云端文件删除失败"+err.Error()) return } } var d interface{} err := global.App.DB.Table("file").Where("id", form.FileId).Delete(d).Error if err != nil { response.Fail(c, 2001, err.Error()) return } response.Success(c, gin.H{}) } func LocalFileToService(c *gin.Context) { form := request.Check(c, &struct { Dir string `form:"dir" json:"dir" binding:"required"` FilePath string `form:"filePath" json:"filePath" binding:"required"` }{}) path, err := FileToService(form.FilePath) if err != nil { response.Fail(c, 1004, err.Error()) return } now := model.XTime{ Time: time.Now(), } //存储到mysql err = global.App.DB.Table("file").Create(&model.File{ CreatedAt: now, UpdatedAt: now, FileName: filepath.Base(form.FilePath), LocalPath: form.FilePath, Type: 1, Dir: form.Dir, CosPath: path, }).Error if err != nil { response.Fail(c, 2001, err.Error()) return } response.Success(c, gin.H{ "file_path": path, }) } func UploadToCos(c *gin.Context) { // 获取文件 file, err := c.FormFile("file") if err != nil { response.Fail(c, 400, "未选择文件") return } //获取dir dir := c.PostForm("dir") if dir == "" { dir = "/" } else if dir != "/" { //格式化 dir = "/" + strings.Trim(dir, "/") + "/" } // 存储路径生成 saveDir := fmt.Sprintf("uploads/%s", dir) os.MkdirAll(saveDir, 0755) savePath := filepath.Join(saveDir, file.Filename) // 保存文件 if err := c.SaveUploadedFile(file, savePath); err != nil { response.Fail(c, 500, "文件保存失败") return } path, err := FileToService(savePath) if err != nil { response.Fail(c, 1004, err.Error()) return } now := model.XTime{ Time: time.Now(), } //存储文件夹 var dirFile model.File base := filepath.Base(dir) dirPath := strings.TrimSuffix(dir, base+"/") fmt.Println("dirPath", dirPath) global.App.DB.Table("file").Where("type", 2).Where("fileName", base).Where("dir", dirPath).First(&dirFile) if dirFile.Id == 0 { err := global.App.DB.Table("file").Create(&model.File{ CreatedAt: now, UpdatedAt: now, FileName: base, Dir: dirPath, LocalPath: "", Type: 2, CosPath: "", }).Error if err != nil { response.Fail(c, 2001, err.Error()) return } } //存储到mysql var files model.File global.App.DB.Table("file").Where("fileName", filepath.Base(savePath)).Where("dir", dir).Find(&files) if files.Id != 0 { err = global.App.DB.Table("file").Where("id", files.Id).Updates(map[string]interface{}{ "localPath": savePath, "updatedAt": now, "fileName": filepath.Base(savePath), "dir": dir, "cosPath": path, }).Error } else { err = global.App.DB.Table("file").Create(&model.File{ CreatedAt: now, UpdatedAt: now, FileName: filepath.Base(savePath), LocalPath: savePath, Type: 1, Dir: dir, CosPath: path, }).Error } if err != nil { response.Fail(c, 2001, err.Error()) return } response.Success(c, gin.H{ "file_path": path, }) } func CreateDir(c *gin.Context) { form := request.Check(c, &struct { Dir string `form:"dir" json:"dir" binding:"required"` DirName string `form:"dirName" json:"dirName" binding:"required"` }{}) count := strings.Count(form.Dir, "/") if count >= 3 { response.Fail(c, 1002, "文件夹的层级不能超过三级") return } now := model.XTime{ Time: time.Now(), } //存储到mysql err := global.App.DB.Table("file").Create(&model.File{ CreatedAt: now, UpdatedAt: now, FileName: form.DirName, Dir: form.Dir, LocalPath: "", Type: 2, CosPath: "", }).Error if err != nil { response.Fail(c, 2001, err.Error()) return } response.Success(c, gin.H{}) } const CosUrl = "https://chunhao-1257323087.cos.ap-shanghai.myqcloud.com" const CosServiceUrl = "https://service.cos.myqcloud.com" const SecretID = "AKIDgQ2TzTq381nQrAJKBC8tSqCNM9lBQTQB" const SecretKey = "gBVWO4dzCD5qeKoy30phTBi7NXYYM2b0" func FileToService(filePath string) (string, error) { // 将 examplebucket-1250000000 和 COS_REGION 修改为用户真实的信息 // 存储桶名称,由 bucketname-appid 组成,appid 必须填入,可以在 COS 控制台查看存储桶名称。https://console.cloud.tencent.com/cos5/bucket // COS_REGION 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket, 关于地域的详情见 https://cloud.tencent.com/document/product/436/6224 u, _ := url.Parse(CosUrl) // 用于 Get Service 查询,默认全地域 service.cos.myqcloud.com su, _ := url.Parse(CosServiceUrl) b := &cos.BaseURL{BucketURL: u, ServiceURL: su} // 1.永久密钥 client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: SecretID, // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140 SecretKey: SecretKey, // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140 }, }) key := filepath.Base(filePath) fmt.Println("key", key) fmt.Println("filePath", filePath) res, _, err := client.Object.Upload( context.Background(), filePath, filePath, nil, ) fmt.Println(res) if err != nil { return "", err } //ourl := client.Object.GetObjectURL(key) return res.Location, nil } func ServiceFileDelete(cosPath string) error { u, _ := url.Parse(CosUrl) // 用于 Get Service 查询,默认全地域 service.cos.myqcloud.com su, _ := url.Parse(CosServiceUrl) b := &cos.BaseURL{BucketURL: u, ServiceURL: su} // 1.永久密钥 client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: SecretID, // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140 SecretKey: SecretKey, // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140 }, }) res, err := client.Object.Delete( context.Background(), cosPath, ) fmt.Println(res) if err != nil { return err } return nil }