local.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package upload
  2. import (
  3. "errors"
  4. "io"
  5. "mime/multipart"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "sync"
  10. "time"
  11. "github.com/flipped-aurora/gin-vue-admin/server/global"
  12. "github.com/flipped-aurora/gin-vue-admin/server/utils"
  13. "go.uber.org/zap"
  14. )
  15. var mu sync.Mutex
  16. type Local struct{}
  17. //@author: [piexlmax](https://github.com/piexlmax)
  18. //@author: [ccfish86](https://github.com/ccfish86)
  19. //@author: [SliverHorn](https://github.com/SliverHorn)
  20. //@object: *Local
  21. //@function: UploadFile
  22. //@description: 上传文件
  23. //@param: file *multipart.FileHeader
  24. //@return: string, string, error
  25. func (*Local) UploadFile(file *multipart.FileHeader) (string, string, error) {
  26. // 读取文件后缀
  27. ext := filepath.Ext(file.Filename)
  28. // 读取文件名并加密
  29. name := strings.TrimSuffix(file.Filename, ext)
  30. name = utils.MD5V([]byte(name))
  31. // 拼接新文件名
  32. filename := name + "_" + time.Now().Format("20060102150405") + ext
  33. // 尝试创建此路径
  34. mkdirErr := os.MkdirAll(global.GVA_CONFIG.Local.StorePath, os.ModePerm)
  35. if mkdirErr != nil {
  36. global.GVA_LOG.Error("function os.MkdirAll() failed", zap.Any("err", mkdirErr.Error()))
  37. return "", "", errors.New("function os.MkdirAll() failed, err:" + mkdirErr.Error())
  38. }
  39. // 拼接路径和文件名
  40. p := global.GVA_CONFIG.Local.StorePath + "/" + filename
  41. filepath := global.GVA_CONFIG.Local.Path + "/" + filename
  42. f, openError := file.Open() // 读取文件
  43. if openError != nil {
  44. global.GVA_LOG.Error("function file.Open() failed", zap.Any("err", openError.Error()))
  45. return "", "", errors.New("function file.Open() failed, err:" + openError.Error())
  46. }
  47. defer f.Close() // 创建文件 defer 关闭
  48. out, createErr := os.Create(p)
  49. if createErr != nil {
  50. global.GVA_LOG.Error("function os.Create() failed", zap.Any("err", createErr.Error()))
  51. return "", "", errors.New("function os.Create() failed, err:" + createErr.Error())
  52. }
  53. defer out.Close() // 创建文件 defer 关闭
  54. _, copyErr := io.Copy(out, f) // 传输(拷贝)文件
  55. if copyErr != nil {
  56. global.GVA_LOG.Error("function io.Copy() failed", zap.Any("err", copyErr.Error()))
  57. return "", "", errors.New("function io.Copy() failed, err:" + copyErr.Error())
  58. }
  59. return filepath, filename, nil
  60. }
  61. //@author: [piexlmax](https://github.com/piexlmax)
  62. //@author: [ccfish86](https://github.com/ccfish86)
  63. //@author: [SliverHorn](https://github.com/SliverHorn)
  64. //@object: *Local
  65. //@function: DeleteFile
  66. //@description: 删除文件
  67. //@param: key string
  68. //@return: error
  69. func (*Local) DeleteFile(key string) error {
  70. // 检查 key 是否为空
  71. if key == "" {
  72. return errors.New("key不能为空")
  73. }
  74. // 验证 key 是否包含非法字符或尝试访问存储路径之外的文件
  75. if strings.Contains(key, "..") || strings.ContainsAny(key, `\/:*?"<>|`) {
  76. return errors.New("非法的key")
  77. }
  78. p := filepath.Join(global.GVA_CONFIG.Local.StorePath, key)
  79. // 检查文件是否存在
  80. if _, err := os.Stat(p); os.IsNotExist(err) {
  81. return errors.New("文件不存在")
  82. }
  83. // 使用文件锁防止并发删除
  84. mu.Lock()
  85. defer mu.Unlock()
  86. err := os.Remove(p)
  87. if err != nil {
  88. return errors.New("文件删除失败: " + err.Error())
  89. }
  90. return nil
  91. }