file.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. package v1
  2. import (
  3. "context"
  4. "designs/app/common/request"
  5. "designs/global"
  6. "designs/model"
  7. "designs/response"
  8. "fmt"
  9. "github.com/gin-gonic/gin"
  10. "github.com/tencentyun/cos-go-sdk-v5"
  11. "net/http"
  12. "net/url"
  13. "os"
  14. "path/filepath"
  15. "strings"
  16. "time"
  17. )
  18. func FileList(c *gin.Context) {
  19. form := request.Check(c, &struct {
  20. Dir string `form:"dir" binding:"required"`
  21. Offset *int `form:"offset" binding:"required"`
  22. Limit *int `form:"limit" binding:"required"`
  23. Search string `form:"search" binding:""`
  24. }{})
  25. query := global.App.DB.Table("file").Where("dir", form.Dir)
  26. if form.Search != "" {
  27. query = query.Where("fileName", "like", "%"+form.Search+"%")
  28. }
  29. var count int64
  30. err := query.Count(&count).Error
  31. if err != nil {
  32. response.Fail(c, 1001, err.Error())
  33. return
  34. }
  35. var files []model.File
  36. err = query.Offset(*form.Offset).Limit(*form.Limit).Scan(&files).Error
  37. if err != nil {
  38. response.Fail(c, 1002, err.Error())
  39. return
  40. }
  41. response.Success(c, gin.H{
  42. "count": count,
  43. "data": files,
  44. })
  45. }
  46. func DirDownload(c *gin.Context) {
  47. form := request.Check(c, &struct {
  48. Dir string `form:"dir" binding:"required"`
  49. }{})
  50. data, err := DirExplode(form.Dir)
  51. if err != nil {
  52. response.Fail(c, 1001, err.Error())
  53. return
  54. }
  55. res := make(map[string]interface{})
  56. dirName := filepath.Base(form.Dir)
  57. res[dirName] = data
  58. data = res
  59. response.Success(c, gin.H{
  60. "data": data,
  61. })
  62. }
  63. func DirExplode(dir string) (map[string]interface{}, error) {
  64. data := make(map[string]interface{})
  65. var files []model.File
  66. err := global.App.DB.Table("file").Where("dir", dir).Scan(&files).Error
  67. if err != nil {
  68. return nil, err
  69. }
  70. for _, file := range files {
  71. if file.Type == 2 {
  72. data[file.FileName], _ = DirExplode(file.Dir + file.FileName + "/")
  73. } else {
  74. data[file.FileName] = file.CosPath
  75. }
  76. }
  77. return data, nil
  78. }
  79. func FileDelete(c *gin.Context) {
  80. form := request.Check(c, &struct {
  81. FileId []int `form:"fileId" json:"fileId" binding:"required"`
  82. }{})
  83. for _, fileId := range form.FileId {
  84. var file model.File
  85. global.App.DB.Table("file").Where("id", fileId).Find(&file)
  86. var d interface{}
  87. err := global.App.DB.Table("file").Where("id", fileId).Delete(d).Error
  88. if err != nil {
  89. response.Fail(c, 2001, err.Error())
  90. return
  91. }
  92. if file.Type == 1 {
  93. //删除本地文件和云端文件 (本地文件暂时不删除,作为备份)
  94. err := ServiceFileDelete(file.CosPath)
  95. if err != nil {
  96. response.Fail(c, 2001, "云端文件删除失败"+err.Error())
  97. return
  98. }
  99. } else if file.Type == 2 {
  100. //文件夹需要删除关联的文件
  101. dirName := file.Dir + file.FileName + "/"
  102. global.App.DB.Table("file").Where("dir", "like", dirName+"%").Delete(d)
  103. }
  104. }
  105. response.Success(c, gin.H{})
  106. }
  107. func LocalFileToService(c *gin.Context) {
  108. form := request.Check(c, &struct {
  109. Dir string `form:"dir" json:"dir" binding:"required"`
  110. FilePath string `form:"filePath" json:"filePath" binding:"required"`
  111. }{})
  112. path, err := FileToService(form.FilePath)
  113. if err != nil {
  114. response.Fail(c, 1004, err.Error())
  115. return
  116. }
  117. now := model.XTime{
  118. Time: time.Now(),
  119. }
  120. //存储到mysql
  121. err = global.App.DB.Table("file").Create(&model.File{
  122. CreatedAt: now,
  123. UpdatedAt: now,
  124. FileName: filepath.Base(form.FilePath),
  125. LocalPath: form.FilePath,
  126. Type: 1,
  127. Dir: form.Dir,
  128. CosPath: path,
  129. }).Error
  130. if err != nil {
  131. response.Fail(c, 2001, err.Error())
  132. return
  133. }
  134. response.Success(c, gin.H{
  135. "file_path": path,
  136. })
  137. }
  138. func UploadToCos(c *gin.Context) {
  139. // 获取文件
  140. file, err := c.FormFile("file")
  141. if err != nil {
  142. response.Fail(c, 400, "未选择文件")
  143. return
  144. }
  145. //获取dir
  146. dir := c.PostForm("dir")
  147. if dir == "" {
  148. dir = "/"
  149. } else if dir != "/" { //格式化
  150. dir = "/" + strings.Trim(dir, "/") + "/"
  151. }
  152. // 存储路径生成
  153. saveDir := fmt.Sprintf("uploads/%s", dir)
  154. os.MkdirAll(saveDir, 0755)
  155. savePath := filepath.Join(saveDir, file.Filename)
  156. // 保存文件
  157. if err := c.SaveUploadedFile(file, savePath); err != nil {
  158. response.Fail(c, 500, "文件保存失败")
  159. return
  160. }
  161. path, err := FileToService(savePath)
  162. if err != nil {
  163. response.Fail(c, 1004, err.Error())
  164. return
  165. }
  166. now := model.XTime{
  167. Time: time.Now(),
  168. }
  169. //存储文件夹
  170. CreateDirs(dir)
  171. //var dirFile model.File
  172. //
  173. //base := filepath.Base(dir)
  174. //dirPath := strings.TrimSuffix(dir, base+"/")
  175. //
  176. //global.App.DB.Table("file").Where("type", 2).Where("fileName", base).Where("dir", dirPath).First(&dirFile)
  177. //if dirFile.Id == 0 {
  178. // global.App.DB.Table("file").Create(&model.File{
  179. // CreatedAt: now,
  180. // UpdatedAt: now,
  181. // FileName: base,
  182. // Dir: dirPath,
  183. // LocalPath: "",
  184. // Type: 2,
  185. // CosPath: "",
  186. // })
  187. //
  188. //}
  189. //存储到mysql
  190. var files model.File
  191. global.App.DB.Table("file").Where("fileName", filepath.Base(savePath)).Where("dir", dir).Find(&files)
  192. if files.Id != 0 {
  193. err = global.App.DB.Table("file").Where("id", files.Id).Updates(map[string]interface{}{
  194. "localPath": savePath,
  195. "updatedAt": now,
  196. "fileName": filepath.Base(savePath),
  197. "dir": dir,
  198. "cosPath": path,
  199. }).Error
  200. } else {
  201. err = global.App.DB.Table("file").Create(&model.File{
  202. CreatedAt: now,
  203. UpdatedAt: now,
  204. FileName: filepath.Base(savePath),
  205. LocalPath: savePath,
  206. Type: 1,
  207. Dir: dir,
  208. CosPath: path,
  209. }).Error
  210. }
  211. if err != nil {
  212. response.Fail(c, 2001, err.Error())
  213. return
  214. }
  215. response.Success(c, gin.H{
  216. "file_path": path,
  217. })
  218. }
  219. func CreateDirs(dir string) {
  220. if dir == "/" || dir == "" {
  221. return
  222. }
  223. base := filepath.Base(dir)
  224. dirPath := strings.TrimSuffix(dir, base+"/")
  225. now := model.XTime{
  226. Time: time.Now(),
  227. }
  228. var dirFile model.File
  229. global.App.DB.Table("file").Where("type", 2).Where("fileName", base).Where("dir", dirPath).First(&dirFile)
  230. if dirFile.Id == 0 {
  231. global.App.DB.Table("file").Create(&model.File{
  232. CreatedAt: now,
  233. UpdatedAt: now,
  234. FileName: base,
  235. Dir: dirPath,
  236. LocalPath: "",
  237. Type: 2,
  238. CosPath: "",
  239. })
  240. }
  241. CreateDirs(dirPath)
  242. }
  243. func CreateDir(c *gin.Context) {
  244. form := request.Check(c, &struct {
  245. Dir string `form:"dir" json:"dir" binding:"required"`
  246. DirName string `form:"dirName" json:"dirName" binding:"required"`
  247. }{})
  248. count := strings.Count(form.Dir, "/")
  249. if count >= 3 {
  250. response.Fail(c, 1002, "文件夹的层级不能超过三级")
  251. return
  252. }
  253. now := model.XTime{
  254. Time: time.Now(),
  255. }
  256. //存储到mysql
  257. err := global.App.DB.Table("file").Create(&model.File{
  258. CreatedAt: now,
  259. UpdatedAt: now,
  260. FileName: form.DirName,
  261. Dir: form.Dir,
  262. LocalPath: "",
  263. Type: 2,
  264. CosPath: "",
  265. }).Error
  266. if err != nil {
  267. response.Fail(c, 2001, err.Error())
  268. return
  269. }
  270. response.Success(c, gin.H{})
  271. }
  272. const CosUrl = "https://chunhao-1257323087.cos.ap-shanghai.myqcloud.com"
  273. const CosServiceUrl = "https://service.cos.myqcloud.com"
  274. const SecretID = "AKIDgQ2TzTq381nQrAJKBC8tSqCNM9lBQTQB"
  275. const SecretKey = "gBVWO4dzCD5qeKoy30phTBi7NXYYM2b0"
  276. func FileToService(filePath string) (string, error) {
  277. // 将 examplebucket-1250000000 和 COS_REGION 修改为用户真实的信息
  278. // 存储桶名称,由 bucketname-appid 组成,appid 必须填入,可以在 COS 控制台查看存储桶名称。https://console.cloud.tencent.com/cos5/bucket
  279. // COS_REGION 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket, 关于地域的详情见 https://cloud.tencent.com/document/product/436/6224
  280. u, _ := url.Parse(CosUrl)
  281. // 用于 Get Service 查询,默认全地域 service.cos.myqcloud.com
  282. su, _ := url.Parse(CosServiceUrl)
  283. b := &cos.BaseURL{BucketURL: u, ServiceURL: su}
  284. // 1.永久密钥
  285. client := cos.NewClient(b, &http.Client{
  286. Transport: &cos.AuthorizationTransport{
  287. SecretID: SecretID, // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
  288. SecretKey: SecretKey, // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
  289. },
  290. })
  291. key := filepath.Base(filePath)
  292. fmt.Println("key", key)
  293. fmt.Println("filePath", filePath)
  294. res, _, err := client.Object.Upload(
  295. context.Background(), filePath, filePath, nil,
  296. )
  297. fmt.Println(res)
  298. if err != nil {
  299. return "", err
  300. }
  301. //ourl := client.Object.GetObjectURL(key)
  302. return res.Location, nil
  303. }
  304. func ServiceFileDelete(cosPath string) error {
  305. u, _ := url.Parse(CosUrl)
  306. // 用于 Get Service 查询,默认全地域 service.cos.myqcloud.com
  307. su, _ := url.Parse(CosServiceUrl)
  308. b := &cos.BaseURL{BucketURL: u, ServiceURL: su}
  309. // 1.永久密钥
  310. client := cos.NewClient(b, &http.Client{
  311. Transport: &cos.AuthorizationTransport{
  312. SecretID: SecretID, // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
  313. SecretKey: SecretKey, // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
  314. },
  315. })
  316. res, err := client.Object.Delete(
  317. context.Background(), cosPath,
  318. )
  319. fmt.Println(res)
  320. if err != nil {
  321. return err
  322. }
  323. return nil
  324. }